params.py revision 10405
19537Satgutier@umich.edu# Copyright (c) 2012-2014 ARM Limited 29537Satgutier@umich.edu# All rights reserved. 39537Satgutier@umich.edu# 49537Satgutier@umich.edu# The license below extends only to copyright in the software and shall 59537Satgutier@umich.edu# not be construed as granting a license to any other intellectual 69537Satgutier@umich.edu# property including but not limited to intellectual property relating 79537Satgutier@umich.edu# to a hardware implementation of the functionality of the software 89537Satgutier@umich.edu# licensed hereunder. You may use the software subject to the license 99537Satgutier@umich.edu# terms below provided that you ensure that this notice is replicated 109537Satgutier@umich.edu# unmodified and in its entirety in all distributions of the software, 119537Satgutier@umich.edu# modified or unmodified, in source code or in binary form. 129537Satgutier@umich.edu# 139537Satgutier@umich.edu# Copyright (c) 2004-2006 The Regents of The University of Michigan 149537Satgutier@umich.edu# Copyright (c) 2010-2011 Advanced Micro Devices, Inc. 159537Satgutier@umich.edu# All rights reserved. 169537Satgutier@umich.edu# 179537Satgutier@umich.edu# Redistribution and use in source and binary forms, with or without 189537Satgutier@umich.edu# modification, are permitted provided that the following conditions are 199537Satgutier@umich.edu# met: redistributions of source code must retain the above copyright 209537Satgutier@umich.edu# notice, this list of conditions and the following disclaimer; 219537Satgutier@umich.edu# redistributions in binary form must reproduce the above copyright 229537Satgutier@umich.edu# notice, this list of conditions and the following disclaimer in the 239537Satgutier@umich.edu# documentation and/or other materials provided with the distribution; 249537Satgutier@umich.edu# neither the name of the copyright holders nor the names of its 259537Satgutier@umich.edu# contributors may be used to endorse or promote products derived from 269537Satgutier@umich.edu# this software without specific prior written permission. 279537Satgutier@umich.edu# 289537Satgutier@umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 299537Satgutier@umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 309537Satgutier@umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 319537Satgutier@umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 329537Satgutier@umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 339537Satgutier@umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 349537Satgutier@umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 359537Satgutier@umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 369537Satgutier@umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 379537Satgutier@umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 389537Satgutier@umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 399537Satgutier@umich.edu# 409537Satgutier@umich.edu# Authors: Steve Reinhardt 419537Satgutier@umich.edu# Nathan Binkert 429537Satgutier@umich.edu# Gabe Black 439537Satgutier@umich.edu# Andreas Hansson 449537Satgutier@umich.edu 459537Satgutier@umich.edu##################################################################### 469537Satgutier@umich.edu# 479537Satgutier@umich.edu# Parameter description classes 489537Satgutier@umich.edu# 499537Satgutier@umich.edu# The _params dictionary in each class maps parameter names to either 509537Satgutier@umich.edu# a Param or a VectorParam object. These objects contain the 519537Satgutier@umich.edu# parameter description string, the parameter type, and the default 529537Satgutier@umich.edu# value (if any). The convert() method on these objects is used to 539537Satgutier@umich.edu# force whatever value is assigned to the parameter to the appropriate 549537Satgutier@umich.edu# type. 559537Satgutier@umich.edu# 569537Satgutier@umich.edu# Note that the default values are loaded into the class's attribute 579537Satgutier@umich.edu# space when the parameter dictionary is initialized (in 589537Satgutier@umich.edu# MetaSimObject._new_param()); after that point they aren't used. 599537Satgutier@umich.edu# 609537Satgutier@umich.edu##################################################################### 619537Satgutier@umich.edu 629537Satgutier@umich.eduimport copy 639537Satgutier@umich.eduimport datetime 649537Satgutier@umich.eduimport re 659537Satgutier@umich.eduimport sys 669537Satgutier@umich.eduimport time 679537Satgutier@umich.eduimport math 689537Satgutier@umich.edu 699537Satgutier@umich.eduimport proxy 709537Satgutier@umich.eduimport ticks 719537Satgutier@umich.edufrom util import * 729537Satgutier@umich.edu 739537Satgutier@umich.edudef isSimObject(*args, **kwargs): 749537Satgutier@umich.edu return SimObject.isSimObject(*args, **kwargs) 759537Satgutier@umich.edu 769537Satgutier@umich.edudef isSimObjectSequence(*args, **kwargs): 779537Satgutier@umich.edu return SimObject.isSimObjectSequence(*args, **kwargs) 789537Satgutier@umich.edu 799537Satgutier@umich.edudef isSimObjectClass(*args, **kwargs): 809537Satgutier@umich.edu return SimObject.isSimObjectClass(*args, **kwargs) 819537Satgutier@umich.edu 829537Satgutier@umich.eduallParams = {} 839537Satgutier@umich.edu 849537Satgutier@umich.educlass MetaParamValue(type): 859537Satgutier@umich.edu def __new__(mcls, name, bases, dct): 869537Satgutier@umich.edu cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) 879537Satgutier@umich.edu assert name not in allParams 889537Satgutier@umich.edu allParams[name] = cls 899537Satgutier@umich.edu return cls 909537Satgutier@umich.edu 919537Satgutier@umich.edu 929537Satgutier@umich.edu# Dummy base class to identify types that are legitimate for SimObject 939537Satgutier@umich.edu# parameters. 949537Satgutier@umich.educlass ParamValue(object): 959537Satgutier@umich.edu __metaclass__ = MetaParamValue 969537Satgutier@umich.edu cmd_line_settable = False 979537Satgutier@umich.edu 989537Satgutier@umich.edu # Generate the code needed as a prerequisite for declaring a C++ 999537Satgutier@umich.edu # object of this type. Typically generates one or more #include 1009537Satgutier@umich.edu # statements. Used when declaring parameters of this type. 1019537Satgutier@umich.edu @classmethod 1029537Satgutier@umich.edu def cxx_predecls(cls, code): 1039537Satgutier@umich.edu pass 1049537Satgutier@umich.edu 1059537Satgutier@umich.edu # Generate the code needed as a prerequisite for including a 1069537Satgutier@umich.edu # reference to a C++ object of this type in a SWIG .i file. 1079537Satgutier@umich.edu # Typically generates one or more %import or %include statements. 1089537Satgutier@umich.edu @classmethod 1099537Satgutier@umich.edu def swig_predecls(cls, code): 1109537Satgutier@umich.edu pass 1119537Satgutier@umich.edu 1129537Satgutier@umich.edu # default for printing to .ini file is regular string conversion. 1139537Satgutier@umich.edu # will be overridden in some cases 1149537Satgutier@umich.edu def ini_str(self): 1159537Satgutier@umich.edu return str(self) 1169537Satgutier@umich.edu 1179537Satgutier@umich.edu # default for printing to .json file is regular string conversion. 1189537Satgutier@umich.edu # will be overridden in some cases, mostly to use native Python 1199537Satgutier@umich.edu # types where there are similar JSON types 1209537Satgutier@umich.edu def config_value(self): 1219537Satgutier@umich.edu return str(self) 1229537Satgutier@umich.edu 1239537Satgutier@umich.edu # allows us to blithely call unproxy() on things without checking 1249537Satgutier@umich.edu # if they're really proxies or not 1259537Satgutier@umich.edu def unproxy(self, base): 1269537Satgutier@umich.edu return self 1279537Satgutier@umich.edu 1289537Satgutier@umich.edu # Produce a human readable version of the stored value 1299537Satgutier@umich.edu def pretty_print(self, value): 1309537Satgutier@umich.edu return str(value) 1319537Satgutier@umich.edu 1329537Satgutier@umich.edu# Regular parameter description. 1339537Satgutier@umich.educlass ParamDesc(object): 1349537Satgutier@umich.edu def __init__(self, ptype_str, ptype, *args, **kwargs): 1359537Satgutier@umich.edu self.ptype_str = ptype_str 1369537Satgutier@umich.edu # remember ptype only if it is provided 1379537Satgutier@umich.edu if ptype != None: 1389537Satgutier@umich.edu self.ptype = ptype 1399537Satgutier@umich.edu 1409537Satgutier@umich.edu if args: 1419537Satgutier@umich.edu if len(args) == 1: 1429537Satgutier@umich.edu self.desc = args[0] 1439537Satgutier@umich.edu elif len(args) == 2: 1449537Satgutier@umich.edu self.default = args[0] 1459537Satgutier@umich.edu self.desc = args[1] 1469537Satgutier@umich.edu else: 1479537Satgutier@umich.edu raise TypeError, 'too many arguments' 1489537Satgutier@umich.edu 1499537Satgutier@umich.edu if kwargs.has_key('desc'): 1509537Satgutier@umich.edu assert(not hasattr(self, 'desc')) 1519537Satgutier@umich.edu self.desc = kwargs['desc'] 1529537Satgutier@umich.edu del kwargs['desc'] 1539537Satgutier@umich.edu 1549537Satgutier@umich.edu if kwargs.has_key('default'): 1559537Satgutier@umich.edu assert(not hasattr(self, 'default')) 1569537Satgutier@umich.edu self.default = kwargs['default'] 1579537Satgutier@umich.edu del kwargs['default'] 1589537Satgutier@umich.edu 1599537Satgutier@umich.edu if kwargs: 1609537Satgutier@umich.edu raise TypeError, 'extra unknown kwargs %s' % kwargs 1619537Satgutier@umich.edu 1629537Satgutier@umich.edu if not hasattr(self, 'desc'): 1639537Satgutier@umich.edu raise TypeError, 'desc attribute missing' 1649537Satgutier@umich.edu 1659537Satgutier@umich.edu def __getattr__(self, attr): 1669537Satgutier@umich.edu if attr == 'ptype': 1679537Satgutier@umich.edu ptype = SimObject.allClasses[self.ptype_str] 1689537Satgutier@umich.edu assert isSimObjectClass(ptype) 1699537Satgutier@umich.edu self.ptype = ptype 1709537Satgutier@umich.edu return ptype 1719537Satgutier@umich.edu 1729537Satgutier@umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 1739537Satgutier@umich.edu (type(self).__name__, attr) 1749537Satgutier@umich.edu 1759537Satgutier@umich.edu def example_str(self): 1769537Satgutier@umich.edu if hasattr(self.ptype, "ex_str"): 1779537Satgutier@umich.edu return self.ptype.ex_str 1789537Satgutier@umich.edu else: 1799537Satgutier@umich.edu return self.ptype_str 1809537Satgutier@umich.edu 1819537Satgutier@umich.edu # Is the param available to be exposed on the command line 1829537Satgutier@umich.edu def isCmdLineSettable(self): 1839537Satgutier@umich.edu if hasattr(self.ptype, "cmd_line_settable"): 1849537Satgutier@umich.edu return self.ptype.cmd_line_settable 1859537Satgutier@umich.edu else: 1869537Satgutier@umich.edu return False 1879537Satgutier@umich.edu 1889537Satgutier@umich.edu def convert(self, value): 1899537Satgutier@umich.edu if isinstance(value, proxy.BaseProxy): 1909537Satgutier@umich.edu value.set_param_desc(self) 1919537Satgutier@umich.edu return value 1929537Satgutier@umich.edu if not hasattr(self, 'ptype') and isNullPointer(value): 1939537Satgutier@umich.edu # deferred evaluation of SimObject; continue to defer if 1949537Satgutier@umich.edu # we're just assigning a null pointer 1959537Satgutier@umich.edu return value 1969537Satgutier@umich.edu if isinstance(value, self.ptype): 1979537Satgutier@umich.edu return value 1989537Satgutier@umich.edu if isNullPointer(value) and isSimObjectClass(self.ptype): 1999537Satgutier@umich.edu return value 2009537Satgutier@umich.edu return self.ptype(value) 2019537Satgutier@umich.edu 2029537Satgutier@umich.edu def pretty_print(self, value): 2039537Satgutier@umich.edu if isinstance(value, proxy.BaseProxy): 2049537Satgutier@umich.edu return str(value) 2059537Satgutier@umich.edu if isNullPointer(value): 2069537Satgutier@umich.edu return NULL 2079537Satgutier@umich.edu return self.ptype(value).pretty_print(value) 2089537Satgutier@umich.edu 2099537Satgutier@umich.edu def cxx_predecls(self, code): 2109537Satgutier@umich.edu code('#include <cstddef>') 2119537Satgutier@umich.edu self.ptype.cxx_predecls(code) 2129537Satgutier@umich.edu 2139537Satgutier@umich.edu def swig_predecls(self, code): 2149537Satgutier@umich.edu self.ptype.swig_predecls(code) 2159537Satgutier@umich.edu 2169537Satgutier@umich.edu def cxx_decl(self, code): 2179537Satgutier@umich.edu code('${{self.ptype.cxx_type}} ${{self.name}};') 2189537Satgutier@umich.edu 2199537Satgutier@umich.edu# Vector-valued parameter description. Just like ParamDesc, except 2209537Satgutier@umich.edu# that the value is a vector (list) of the specified type instead of a 2219537Satgutier@umich.edu# single value. 2229537Satgutier@umich.edu 2239537Satgutier@umich.educlass VectorParamValue(list): 2249537Satgutier@umich.edu __metaclass__ = MetaParamValue 2259537Satgutier@umich.edu def __setattr__(self, attr, value): 2269537Satgutier@umich.edu raise AttributeError, \ 2279537Satgutier@umich.edu "Not allowed to set %s on '%s'" % (attr, type(self).__name__) 2289537Satgutier@umich.edu 2299537Satgutier@umich.edu def config_value(self): 2309537Satgutier@umich.edu return [v.config_value() for v in self] 2319537Satgutier@umich.edu 2329537Satgutier@umich.edu def ini_str(self): 2339537Satgutier@umich.edu return ' '.join([v.ini_str() for v in self]) 2349537Satgutier@umich.edu 2359537Satgutier@umich.edu def getValue(self): 2369537Satgutier@umich.edu return [ v.getValue() for v in self ] 2379537Satgutier@umich.edu 2389537Satgutier@umich.edu def unproxy(self, base): 2399537Satgutier@umich.edu if len(self) == 1 and isinstance(self[0], proxy.AllProxy): 2409537Satgutier@umich.edu return self[0].unproxy(base) 2419537Satgutier@umich.edu else: 2429537Satgutier@umich.edu return [v.unproxy(base) for v in self] 2439537Satgutier@umich.edu 2449537Satgutier@umich.educlass SimObjectVector(VectorParamValue): 2459537Satgutier@umich.edu # support clone operation 2469537Satgutier@umich.edu def __call__(self, **kwargs): 2479537Satgutier@umich.edu return SimObjectVector([v(**kwargs) for v in self]) 2489537Satgutier@umich.edu 2499537Satgutier@umich.edu def clear_parent(self, old_parent): 2509537Satgutier@umich.edu for v in self: 2519537Satgutier@umich.edu v.clear_parent(old_parent) 2529537Satgutier@umich.edu 2539537Satgutier@umich.edu def set_parent(self, parent, name): 2549537Satgutier@umich.edu if len(self) == 1: 2559537Satgutier@umich.edu self[0].set_parent(parent, name) 2569537Satgutier@umich.edu else: 2579537Satgutier@umich.edu width = int(math.ceil(math.log(len(self))/math.log(10))) 2589537Satgutier@umich.edu for i,v in enumerate(self): 2599537Satgutier@umich.edu v.set_parent(parent, "%s%0*d" % (name, width, i)) 2609537Satgutier@umich.edu 2619537Satgutier@umich.edu def has_parent(self): 2629537Satgutier@umich.edu return reduce(lambda x,y: x and y, [v.has_parent() for v in self]) 2639537Satgutier@umich.edu 2649537Satgutier@umich.edu # return 'cpu0 cpu1' etc. for print_ini() 2659537Satgutier@umich.edu def get_name(self): 2669537Satgutier@umich.edu return ' '.join([v._name for v in self]) 2679537Satgutier@umich.edu 2689537Satgutier@umich.edu # By iterating through the constituent members of the vector here 2699537Satgutier@umich.edu # we can nicely handle iterating over all a SimObject's children 2709537Satgutier@umich.edu # without having to provide lots of special functions on 2719537Satgutier@umich.edu # SimObjectVector directly. 2729537Satgutier@umich.edu def descendants(self): 2739537Satgutier@umich.edu for v in self: 2749537Satgutier@umich.edu for obj in v.descendants(): 2759537Satgutier@umich.edu yield obj 2769537Satgutier@umich.edu 2779537Satgutier@umich.edu def get_config_as_dict(self): 2789537Satgutier@umich.edu a = [] 2799537Satgutier@umich.edu for v in self: 2809537Satgutier@umich.edu a.append(v.get_config_as_dict()) 2819537Satgutier@umich.edu return a 2829537Satgutier@umich.edu 2839537Satgutier@umich.edu # If we are replacing an item in the vector, make sure to set the 2849537Satgutier@umich.edu # parent reference of the new SimObject to be the same as the parent 2859537Satgutier@umich.edu # of the SimObject being replaced. Useful to have if we created 2869537Satgutier@umich.edu # a SimObjectVector of temporary objects that will be modified later in 2879537Satgutier@umich.edu # configuration scripts. 2889537Satgutier@umich.edu def __setitem__(self, key, value): 2899537Satgutier@umich.edu val = self[key] 2909537Satgutier@umich.edu if value.has_parent(): 2919537Satgutier@umich.edu warn("SimObject %s already has a parent" % value.get_name() +\ 2929537Satgutier@umich.edu " that is being overwritten by a SimObjectVector") 2939537Satgutier@umich.edu value.set_parent(val.get_parent(), val._name) 2949537Satgutier@umich.edu super(SimObjectVector, self).__setitem__(key, value) 2959537Satgutier@umich.edu 2969537Satgutier@umich.edu # Enumerate the params of each member of the SimObject vector. Creates 2979537Satgutier@umich.edu # strings that will allow indexing into the vector by the python code and 2989537Satgutier@umich.edu # allow it to be specified on the command line. 2999537Satgutier@umich.edu def enumerateParams(self, flags_dict = {}, 3009537Satgutier@umich.edu cmd_line_str = "", 3019537Satgutier@umich.edu access_str = ""): 3029537Satgutier@umich.edu if hasattr(self, "_paramEnumed"): 3039537Satgutier@umich.edu print "Cycle detected enumerating params at %s?!" % (cmd_line_str) 3049537Satgutier@umich.edu else: 3059537Satgutier@umich.edu x = 0 3069537Satgutier@umich.edu for vals in self: 3079537Satgutier@umich.edu # Each entry in the SimObjectVector should be an 3089537Satgutier@umich.edu # instance of a SimObject 3099537Satgutier@umich.edu flags_dict = vals.enumerateParams(flags_dict, 3109537Satgutier@umich.edu cmd_line_str + "%d." % x, 3119537Satgutier@umich.edu access_str + "[%d]." % x) 3129537Satgutier@umich.edu x = x + 1 3139537Satgutier@umich.edu 3149537Satgutier@umich.edu return flags_dict 3159537Satgutier@umich.edu 3169537Satgutier@umich.educlass VectorParamDesc(ParamDesc): 3179537Satgutier@umich.edu # Convert assigned value to appropriate type. If the RHS is not a 3189537Satgutier@umich.edu # list or tuple, it generates a single-element list. 3199537Satgutier@umich.edu def convert(self, value): 3209537Satgutier@umich.edu if isinstance(value, (list, tuple)): 3219537Satgutier@umich.edu # list: coerce each element into new list 3229537Satgutier@umich.edu tmp_list = [ ParamDesc.convert(self, v) for v in value ] 3239537Satgutier@umich.edu elif isinstance(value, str): 3249537Satgutier@umich.edu # If input is a csv string 3259537Satgutier@umich.edu tmp_list = [ ParamDesc.convert(self, v) \ 3269537Satgutier@umich.edu for v in value.strip('[').strip(']').split(',') ] 3279537Satgutier@umich.edu else: 3289537Satgutier@umich.edu # singleton: coerce to a single-element list 3299537Satgutier@umich.edu tmp_list = [ ParamDesc.convert(self, value) ] 3309537Satgutier@umich.edu 3319537Satgutier@umich.edu if isSimObjectSequence(tmp_list): 3329537Satgutier@umich.edu return SimObjectVector(tmp_list) 3339537Satgutier@umich.edu else: 3349537Satgutier@umich.edu return VectorParamValue(tmp_list) 3359537Satgutier@umich.edu 3369537Satgutier@umich.edu # Produce a human readable example string that describes 3379537Satgutier@umich.edu # how to set this vector parameter in the absence of a default 3389537Satgutier@umich.edu # value. 3399537Satgutier@umich.edu def example_str(self): 3409537Satgutier@umich.edu s = super(VectorParamDesc, self).example_str() 3419537Satgutier@umich.edu help_str = "[" + s + "," + s + ", ...]" 3429537Satgutier@umich.edu return help_str 3439537Satgutier@umich.edu 3449537Satgutier@umich.edu # Produce a human readable representation of the value of this vector param. 3459537Satgutier@umich.edu def pretty_print(self, value): 3469537Satgutier@umich.edu if isinstance(value, (list, tuple)): 3479537Satgutier@umich.edu tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ] 3489537Satgutier@umich.edu elif isinstance(value, str): 3499537Satgutier@umich.edu tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ] 3509537Satgutier@umich.edu else: 3519537Satgutier@umich.edu tmp_list = [ ParamDesc.pretty_print(self, value) ] 3529537Satgutier@umich.edu 3539537Satgutier@umich.edu return tmp_list 3549537Satgutier@umich.edu 3559537Satgutier@umich.edu # This is a helper function for the new config system 3569537Satgutier@umich.edu def __call__(self, value): 3579537Satgutier@umich.edu if isinstance(value, (list, tuple)): 3589537Satgutier@umich.edu # list: coerce each element into new list 3599537Satgutier@umich.edu tmp_list = [ ParamDesc.convert(self, v) for v in value ] 3609537Satgutier@umich.edu elif isinstance(value, str): 3619537Satgutier@umich.edu # If input is a csv string 3629537Satgutier@umich.edu tmp_list = [ ParamDesc.convert(self, v) \ 3639537Satgutier@umich.edu for v in value.strip('[').strip(']').split(',') ] 3649537Satgutier@umich.edu else: 3659537Satgutier@umich.edu # singleton: coerce to a single-element list 3669537Satgutier@umich.edu tmp_list = [ ParamDesc.convert(self, value) ] 3679537Satgutier@umich.edu 3689537Satgutier@umich.edu return VectorParamValue(tmp_list) 3699537Satgutier@umich.edu 3709537Satgutier@umich.edu def swig_module_name(self): 3719537Satgutier@umich.edu return "%s_vector" % self.ptype_str 3729537Satgutier@umich.edu 3739537Satgutier@umich.edu def swig_predecls(self, code): 3749537Satgutier@umich.edu code('%import "${{self.swig_module_name()}}.i"') 3759537Satgutier@umich.edu 3769537Satgutier@umich.edu def swig_decl(self, code): 3779537Satgutier@umich.edu code('%module(package="m5.internal") ${{self.swig_module_name()}}') 3789537Satgutier@umich.edu code('%{') 3799537Satgutier@umich.edu self.ptype.cxx_predecls(code) 3809537Satgutier@umich.edu code('%}') 3819537Satgutier@umich.edu code() 3829537Satgutier@umich.edu # Make sure the SWIGPY_SLICE_ARG is defined through this inclusion 3839537Satgutier@umich.edu code('%include "std_container.i"') 3849537Satgutier@umich.edu code() 3859537Satgutier@umich.edu self.ptype.swig_predecls(code) 3869537Satgutier@umich.edu code() 3879537Satgutier@umich.edu code('%include "std_vector.i"') 3889537Satgutier@umich.edu code() 3899537Satgutier@umich.edu 3909537Satgutier@umich.edu ptype = self.ptype_str 3919537Satgutier@umich.edu cxx_type = self.ptype.cxx_type 3929537Satgutier@umich.edu 3939537Satgutier@umich.edu code('%template(vector_$ptype) std::vector< $cxx_type >;') 3949537Satgutier@umich.edu 3959537Satgutier@umich.edu def cxx_predecls(self, code): 3969537Satgutier@umich.edu code('#include <vector>') 3979537Satgutier@umich.edu self.ptype.cxx_predecls(code) 3989537Satgutier@umich.edu 3999537Satgutier@umich.edu def cxx_decl(self, code): 4009537Satgutier@umich.edu code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};') 4019537Satgutier@umich.edu 4029537Satgutier@umich.educlass ParamFactory(object): 4039537Satgutier@umich.edu def __init__(self, param_desc_class, ptype_str = None): 4049537Satgutier@umich.edu self.param_desc_class = param_desc_class 4059537Satgutier@umich.edu self.ptype_str = ptype_str 4069537Satgutier@umich.edu 4079537Satgutier@umich.edu def __getattr__(self, attr): 4089537Satgutier@umich.edu if self.ptype_str: 4099537Satgutier@umich.edu attr = self.ptype_str + '.' + attr 4109537Satgutier@umich.edu return ParamFactory(self.param_desc_class, attr) 4119537Satgutier@umich.edu 4129537Satgutier@umich.edu # E.g., Param.Int(5, "number of widgets") 4139537Satgutier@umich.edu def __call__(self, *args, **kwargs): 4149537Satgutier@umich.edu ptype = None 4159537Satgutier@umich.edu try: 4169537Satgutier@umich.edu ptype = allParams[self.ptype_str] 4179537Satgutier@umich.edu except KeyError: 4189537Satgutier@umich.edu # if name isn't defined yet, assume it's a SimObject, and 4199537Satgutier@umich.edu # try to resolve it later 4209537Satgutier@umich.edu pass 4219537Satgutier@umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 4229537Satgutier@umich.edu 4239537Satgutier@umich.eduParam = ParamFactory(ParamDesc) 4249537Satgutier@umich.eduVectorParam = ParamFactory(VectorParamDesc) 4259537Satgutier@umich.edu 4269537Satgutier@umich.edu##################################################################### 4279537Satgutier@umich.edu# 4289537Satgutier@umich.edu# Parameter Types 4299537Satgutier@umich.edu# 4309537Satgutier@umich.edu# Though native Python types could be used to specify parameter types 4319537Satgutier@umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more 4329537Satgutier@umich.edu# flexible to define our own set of types. This gives us more control 4339537Satgutier@umich.edu# over how Python expressions are converted to values (via the 4349537Satgutier@umich.edu# __init__() constructor) and how these values are printed out (via 4359537Satgutier@umich.edu# the __str__() conversion method). 4369537Satgutier@umich.edu# 4379537Satgutier@umich.edu##################################################################### 4389537Satgutier@umich.edu 4399537Satgutier@umich.edu# String-valued parameter. Just mixin the ParamValue class with the 4409537Satgutier@umich.edu# built-in str class. 4419537Satgutier@umich.educlass String(ParamValue,str): 4429537Satgutier@umich.edu cxx_type = 'std::string' 4439537Satgutier@umich.edu cmd_line_settable = True 4449537Satgutier@umich.edu 4459537Satgutier@umich.edu @classmethod 4469537Satgutier@umich.edu def cxx_predecls(self, code): 4479537Satgutier@umich.edu code('#include <string>') 4489537Satgutier@umich.edu 4499537Satgutier@umich.edu @classmethod 4509537Satgutier@umich.edu def swig_predecls(cls, code): 4519537Satgutier@umich.edu code('%include "std_string.i"') 4529537Satgutier@umich.edu 4539537Satgutier@umich.edu def __call__(self, value): 4549537Satgutier@umich.edu self = value 4559537Satgutier@umich.edu return value 4569537Satgutier@umich.edu 4579537Satgutier@umich.edu def getValue(self): 4589537Satgutier@umich.edu return self 4599537Satgutier@umich.edu 4609537Satgutier@umich.edu# superclass for "numeric" parameter values, to emulate math 4619537Satgutier@umich.edu# operations in a type-safe way. e.g., a Latency times an int returns 4629537Satgutier@umich.edu# a new Latency object. 4639537Satgutier@umich.educlass NumericParamValue(ParamValue): 4649537Satgutier@umich.edu def __str__(self): 4659537Satgutier@umich.edu return str(self.value) 4669537Satgutier@umich.edu 4679537Satgutier@umich.edu def __float__(self): 4689537Satgutier@umich.edu return float(self.value) 4699537Satgutier@umich.edu 4709537Satgutier@umich.edu def __long__(self): 4719537Satgutier@umich.edu return long(self.value) 4729537Satgutier@umich.edu 4739537Satgutier@umich.edu def __int__(self): 4749537Satgutier@umich.edu return int(self.value) 4759537Satgutier@umich.edu 4769537Satgutier@umich.edu # hook for bounds checking 4779537Satgutier@umich.edu def _check(self): 4789537Satgutier@umich.edu return 4799537Satgutier@umich.edu 4809537Satgutier@umich.edu def __mul__(self, other): 4819537Satgutier@umich.edu newobj = self.__class__(self) 4829537Satgutier@umich.edu newobj.value *= other 4839537Satgutier@umich.edu newobj._check() 4849537Satgutier@umich.edu return newobj 4859537Satgutier@umich.edu 4869537Satgutier@umich.edu __rmul__ = __mul__ 4879537Satgutier@umich.edu 4889537Satgutier@umich.edu def __div__(self, other): 4899537Satgutier@umich.edu newobj = self.__class__(self) 4909537Satgutier@umich.edu newobj.value /= other 4919537Satgutier@umich.edu newobj._check() 4929537Satgutier@umich.edu return newobj 4939537Satgutier@umich.edu 4949537Satgutier@umich.edu def __sub__(self, other): 4959537Satgutier@umich.edu newobj = self.__class__(self) 4969537Satgutier@umich.edu newobj.value -= other 4979537Satgutier@umich.edu newobj._check() 4989537Satgutier@umich.edu return newobj 4999537Satgutier@umich.edu 5009537Satgutier@umich.edu def config_value(self): 5019537Satgutier@umich.edu return self.value 5029537Satgutier@umich.edu 5039537Satgutier@umich.edu# Metaclass for bounds-checked integer parameters. See CheckedInt. 5049537Satgutier@umich.educlass CheckedIntType(MetaParamValue): 5059537Satgutier@umich.edu def __init__(cls, name, bases, dict): 5069537Satgutier@umich.edu super(CheckedIntType, cls).__init__(name, bases, dict) 5079537Satgutier@umich.edu 5089537Satgutier@umich.edu # CheckedInt is an abstract base class, so we actually don't 5099537Satgutier@umich.edu # want to do any processing on it... the rest of this code is 5109537Satgutier@umich.edu # just for classes that derive from CheckedInt. 5119537Satgutier@umich.edu if name == 'CheckedInt': 5129537Satgutier@umich.edu return 5139537Satgutier@umich.edu 5149537Satgutier@umich.edu if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 5159537Satgutier@umich.edu if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 5169537Satgutier@umich.edu panic("CheckedInt subclass %s must define either\n" \ 5179537Satgutier@umich.edu " 'min' and 'max' or 'size' and 'unsigned'\n", 5189537Satgutier@umich.edu name); 5199537Satgutier@umich.edu if cls.unsigned: 5209537Satgutier@umich.edu cls.min = 0 5219537Satgutier@umich.edu cls.max = 2 ** cls.size - 1 5229537Satgutier@umich.edu else: 5239537Satgutier@umich.edu cls.min = -(2 ** (cls.size - 1)) 5249537Satgutier@umich.edu cls.max = (2 ** (cls.size - 1)) - 1 5259537Satgutier@umich.edu 5269537Satgutier@umich.edu# Abstract superclass for bounds-checked integer parameters. This 5279537Satgutier@umich.edu# class is subclassed to generate parameter classes with specific 5289537Satgutier@umich.edu# bounds. Initialization of the min and max bounds is done in the 5299537Satgutier@umich.edu# metaclass CheckedIntType.__init__. 5309537Satgutier@umich.educlass CheckedInt(NumericParamValue): 5319537Satgutier@umich.edu __metaclass__ = CheckedIntType 5329537Satgutier@umich.edu cmd_line_settable = True 5339537Satgutier@umich.edu 5349537Satgutier@umich.edu def _check(self): 5359537Satgutier@umich.edu if not self.min <= self.value <= self.max: 5369537Satgutier@umich.edu raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 5379537Satgutier@umich.edu (self.min, self.value, self.max) 5389537Satgutier@umich.edu 5399537Satgutier@umich.edu def __init__(self, value): 5409537Satgutier@umich.edu if isinstance(value, str): 5419537Satgutier@umich.edu self.value = convert.toInteger(value) 5429537Satgutier@umich.edu elif isinstance(value, (int, long, float, NumericParamValue)): 5439537Satgutier@umich.edu self.value = long(value) 5449537Satgutier@umich.edu else: 5459537Satgutier@umich.edu raise TypeError, "Can't convert object of type %s to CheckedInt" \ 5469537Satgutier@umich.edu % type(value).__name__ 5479537Satgutier@umich.edu self._check() 5489537Satgutier@umich.edu 5499537Satgutier@umich.edu def __call__(self, value): 5509537Satgutier@umich.edu self.__init__(value) 5519537Satgutier@umich.edu return value 5529537Satgutier@umich.edu 5539537Satgutier@umich.edu @classmethod 5549537Satgutier@umich.edu def cxx_predecls(cls, code): 5559537Satgutier@umich.edu # most derived types require this, so we just do it here once 5569537Satgutier@umich.edu code('#include "base/types.hh"') 5579537Satgutier@umich.edu 5589537Satgutier@umich.edu @classmethod 5599537Satgutier@umich.edu def swig_predecls(cls, code): 5609537Satgutier@umich.edu # most derived types require this, so we just do it here once 5619537Satgutier@umich.edu code('%import "stdint.i"') 5629537Satgutier@umich.edu code('%import "base/types.hh"') 5639537Satgutier@umich.edu 5649537Satgutier@umich.edu def getValue(self): 5659537Satgutier@umich.edu return long(self.value) 5669537Satgutier@umich.edu 5679537Satgutier@umich.educlass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 5689537Satgutier@umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 5699537Satgutier@umich.edu 5709537Satgutier@umich.educlass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 5719537Satgutier@umich.educlass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 5729537Satgutier@umich.educlass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 5739537Satgutier@umich.educlass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 5749537Satgutier@umich.educlass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 5759537Satgutier@umich.educlass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 5769537Satgutier@umich.educlass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 5779537Satgutier@umich.educlass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 5789537Satgutier@umich.edu 5799537Satgutier@umich.educlass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 5809537Satgutier@umich.educlass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 5819537Satgutier@umich.educlass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 5829537Satgutier@umich.educlass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 5839537Satgutier@umich.edu 5849537Satgutier@umich.educlass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 5859537Satgutier@umich.edu 5869537Satgutier@umich.educlass Cycles(CheckedInt): 5879537Satgutier@umich.edu cxx_type = 'Cycles' 5889537Satgutier@umich.edu size = 64 5899537Satgutier@umich.edu unsigned = True 5909537Satgutier@umich.edu 5919537Satgutier@umich.edu def getValue(self): 5929537Satgutier@umich.edu from m5.internal.core import Cycles 5939537Satgutier@umich.edu return Cycles(self.value) 5949537Satgutier@umich.edu 5959537Satgutier@umich.educlass Float(ParamValue, float): 5969537Satgutier@umich.edu cxx_type = 'double' 5979537Satgutier@umich.edu cmdLineSettable = True 5989537Satgutier@umich.edu 5999537Satgutier@umich.edu def __init__(self, value): 6009537Satgutier@umich.edu if isinstance(value, (int, long, float, NumericParamValue, Float, str)): 6019537Satgutier@umich.edu self.value = float(value) 6029537Satgutier@umich.edu else: 6039537Satgutier@umich.edu raise TypeError, "Can't convert object of type %s to Float" \ 6049537Satgutier@umich.edu % type(value).__name__ 6059537Satgutier@umich.edu 6069537Satgutier@umich.edu def __call__(self, value): 6079537Satgutier@umich.edu self.__init__(value) 6089537Satgutier@umich.edu return value 6099537Satgutier@umich.edu 6109537Satgutier@umich.edu def getValue(self): 6119537Satgutier@umich.edu return float(self.value) 6129537Satgutier@umich.edu 6139537Satgutier@umich.edu def config_value(self): 6149537Satgutier@umich.edu return self 6159537Satgutier@umich.edu 6169537Satgutier@umich.educlass MemorySize(CheckedInt): 6179537Satgutier@umich.edu cxx_type = 'uint64_t' 6189537Satgutier@umich.edu ex_str = '512MB' 6199537Satgutier@umich.edu size = 64 6209537Satgutier@umich.edu unsigned = True 6219537Satgutier@umich.edu def __init__(self, value): 6229537Satgutier@umich.edu if isinstance(value, MemorySize): 6239537Satgutier@umich.edu self.value = value.value 6249537Satgutier@umich.edu else: 6259537Satgutier@umich.edu self.value = convert.toMemorySize(value) 6269537Satgutier@umich.edu self._check() 6279537Satgutier@umich.edu 6289537Satgutier@umich.educlass MemorySize32(CheckedInt): 6299537Satgutier@umich.edu cxx_type = 'uint32_t' 6309537Satgutier@umich.edu ex_str = '512MB' 6319537Satgutier@umich.edu size = 32 6329537Satgutier@umich.edu unsigned = True 6339537Satgutier@umich.edu def __init__(self, value): 6349537Satgutier@umich.edu if isinstance(value, MemorySize): 6359537Satgutier@umich.edu self.value = value.value 6369537Satgutier@umich.edu else: 6379537Satgutier@umich.edu self.value = convert.toMemorySize(value) 6389537Satgutier@umich.edu self._check() 6399537Satgutier@umich.edu 6409537Satgutier@umich.educlass Addr(CheckedInt): 6419537Satgutier@umich.edu cxx_type = 'Addr' 6429537Satgutier@umich.edu size = 64 6439537Satgutier@umich.edu unsigned = True 6449537Satgutier@umich.edu def __init__(self, value): 6459537Satgutier@umich.edu if isinstance(value, Addr): 6469537Satgutier@umich.edu self.value = value.value 6479537Satgutier@umich.edu else: 6489537Satgutier@umich.edu try: 6499537Satgutier@umich.edu # Often addresses are referred to with sizes. Ex: A device 6509537Satgutier@umich.edu # base address is at "512MB". Use toMemorySize() to convert 6519537Satgutier@umich.edu # these into addresses. If the address is not specified with a 6529537Satgutier@umich.edu # "size", an exception will occur and numeric translation will 6539537Satgutier@umich.edu # proceed below. 6549537Satgutier@umich.edu self.value = convert.toMemorySize(value) 6559537Satgutier@umich.edu except (TypeError, ValueError): 6569537Satgutier@umich.edu # Convert number to string and use long() to do automatic 6579537Satgutier@umich.edu # base conversion (requires base=0 for auto-conversion) 6589537Satgutier@umich.edu self.value = long(str(value), base=0) 6599537Satgutier@umich.edu 6609537Satgutier@umich.edu self._check() 6619537Satgutier@umich.edu def __add__(self, other): 6629537Satgutier@umich.edu if isinstance(other, Addr): 6639537Satgutier@umich.edu return self.value + other.value 6649537Satgutier@umich.edu else: 6659537Satgutier@umich.edu return self.value + other 6669537Satgutier@umich.edu def pretty_print(self, value): 6679537Satgutier@umich.edu try: 6689537Satgutier@umich.edu val = convert.toMemorySize(value) 6699537Satgutier@umich.edu except TypeError: 6709537Satgutier@umich.edu val = long(value) 6719537Satgutier@umich.edu return "0x%x" % long(val) 6729537Satgutier@umich.edu 6739537Satgutier@umich.educlass AddrRange(ParamValue): 6749537Satgutier@umich.edu cxx_type = 'AddrRange' 6759537Satgutier@umich.edu 6769537Satgutier@umich.edu def __init__(self, *args, **kwargs): 6779537Satgutier@umich.edu # Disable interleaving by default 6789537Satgutier@umich.edu self.intlvHighBit = 0 6799537Satgutier@umich.edu self.intlvBits = 0 6809537Satgutier@umich.edu self.intlvMatch = 0 6819537Satgutier@umich.edu 6829537Satgutier@umich.edu def handle_kwargs(self, kwargs): 6839537Satgutier@umich.edu # An address range needs to have an upper limit, specified 6849537Satgutier@umich.edu # either explicitly with an end, or as an offset using the 6859537Satgutier@umich.edu # size keyword. 6869537Satgutier@umich.edu if 'end' in kwargs: 6879537Satgutier@umich.edu self.end = Addr(kwargs.pop('end')) 6889537Satgutier@umich.edu elif 'size' in kwargs: 6899537Satgutier@umich.edu self.end = self.start + Addr(kwargs.pop('size')) - 1 6909537Satgutier@umich.edu else: 6919537Satgutier@umich.edu raise TypeError, "Either end or size must be specified" 6929537Satgutier@umich.edu 6939537Satgutier@umich.edu # Now on to the optional bit 6949537Satgutier@umich.edu if 'intlvHighBit' in kwargs: 6959537Satgutier@umich.edu self.intlvHighBit = int(kwargs.pop('intlvHighBit')) 6969537Satgutier@umich.edu if 'intlvBits' in kwargs: 6979537Satgutier@umich.edu self.intlvBits = int(kwargs.pop('intlvBits')) 6989537Satgutier@umich.edu if 'intlvMatch' in kwargs: 6999537Satgutier@umich.edu self.intlvMatch = int(kwargs.pop('intlvMatch')) 7009537Satgutier@umich.edu 7019537Satgutier@umich.edu if len(args) == 0: 7029537Satgutier@umich.edu self.start = Addr(kwargs.pop('start')) 7039537Satgutier@umich.edu handle_kwargs(self, kwargs) 7049537Satgutier@umich.edu 7059537Satgutier@umich.edu elif len(args) == 1: 7069537Satgutier@umich.edu if kwargs: 7079537Satgutier@umich.edu self.start = Addr(args[0]) 7089537Satgutier@umich.edu handle_kwargs(self, kwargs) 7099537Satgutier@umich.edu elif isinstance(args[0], (list, tuple)): 7109537Satgutier@umich.edu self.start = Addr(args[0][0]) 7119537Satgutier@umich.edu self.end = Addr(args[0][1]) 7129537Satgutier@umich.edu else: 7139537Satgutier@umich.edu self.start = Addr(0) 7149537Satgutier@umich.edu self.end = Addr(args[0]) - 1 7159537Satgutier@umich.edu 7169537Satgutier@umich.edu elif len(args) == 2: 7179537Satgutier@umich.edu self.start = Addr(args[0]) 7189537Satgutier@umich.edu self.end = Addr(args[1]) 7199537Satgutier@umich.edu else: 7209537Satgutier@umich.edu raise TypeError, "Too many arguments specified" 7219537Satgutier@umich.edu 7229537Satgutier@umich.edu if kwargs: 7239537Satgutier@umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 7249537Satgutier@umich.edu 7259537Satgutier@umich.edu def __str__(self): 7269537Satgutier@umich.edu return '%s:%s' % (self.start, self.end) 7279537Satgutier@umich.edu 7289537Satgutier@umich.edu def size(self): 7299537Satgutier@umich.edu # Divide the size by the size of the interleaving slice 7309537Satgutier@umich.edu return (long(self.end) - long(self.start) + 1) >> self.intlvBits 7319537Satgutier@umich.edu 7329537Satgutier@umich.edu @classmethod 7339537Satgutier@umich.edu def cxx_predecls(cls, code): 7349537Satgutier@umich.edu Addr.cxx_predecls(code) 7359537Satgutier@umich.edu code('#include "base/addr_range.hh"') 7369537Satgutier@umich.edu 7379537Satgutier@umich.edu @classmethod 7389537Satgutier@umich.edu def swig_predecls(cls, code): 7399537Satgutier@umich.edu Addr.swig_predecls(code) 7409537Satgutier@umich.edu 7419537Satgutier@umich.edu def getValue(self): 7429537Satgutier@umich.edu # Go from the Python class to the wrapped C++ class generated 7439537Satgutier@umich.edu # by swig 7449537Satgutier@umich.edu from m5.internal.range import AddrRange 7459537Satgutier@umich.edu 7469537Satgutier@umich.edu return AddrRange(long(self.start), long(self.end), 7479537Satgutier@umich.edu int(self.intlvHighBit), int(self.intlvBits), 7489537Satgutier@umich.edu int(self.intlvMatch)) 7499537Satgutier@umich.edu 7509537Satgutier@umich.edu# Boolean parameter type. Python doesn't let you subclass bool, since 7519537Satgutier@umich.edu# it doesn't want to let you create multiple instances of True and 7529537Satgutier@umich.edu# False. Thus this is a little more complicated than String. 7539537Satgutier@umich.educlass Bool(ParamValue): 7549537Satgutier@umich.edu cxx_type = 'bool' 7559537Satgutier@umich.edu cmd_line_settable = True 7569537Satgutier@umich.edu 7579537Satgutier@umich.edu def __init__(self, value): 7589537Satgutier@umich.edu try: 7599537Satgutier@umich.edu self.value = convert.toBool(value) 7609537Satgutier@umich.edu except TypeError: 7619537Satgutier@umich.edu self.value = bool(value) 7629537Satgutier@umich.edu 7639537Satgutier@umich.edu def __call__(self, value): 7649537Satgutier@umich.edu self.__init__(value) 7659537Satgutier@umich.edu return value 7669537Satgutier@umich.edu 7679537Satgutier@umich.edu def getValue(self): 7689537Satgutier@umich.edu return bool(self.value) 7699537Satgutier@umich.edu 7709537Satgutier@umich.edu def __str__(self): 7719537Satgutier@umich.edu return str(self.value) 7729537Satgutier@umich.edu 7739537Satgutier@umich.edu # implement truth value testing for Bool parameters so that these params 7749537Satgutier@umich.edu # evaluate correctly during the python configuration phase 7759537Satgutier@umich.edu def __nonzero__(self): 7769537Satgutier@umich.edu return bool(self.value) 7779537Satgutier@umich.edu 7789537Satgutier@umich.edu def ini_str(self): 7799537Satgutier@umich.edu if self.value: 7809537Satgutier@umich.edu return 'true' 7819537Satgutier@umich.edu return 'false' 7829537Satgutier@umich.edu 7839537Satgutier@umich.edu def config_value(self): 7849537Satgutier@umich.edu return self.value 7859537Satgutier@umich.edu 7869537Satgutier@umich.edudef IncEthernetAddr(addr, val = 1): 7879537Satgutier@umich.edu bytes = map(lambda x: int(x, 16), addr.split(':')) 7889537Satgutier@umich.edu bytes[5] += val 7899537Satgutier@umich.edu for i in (5, 4, 3, 2, 1): 7909537Satgutier@umich.edu val,rem = divmod(bytes[i], 256) 7919537Satgutier@umich.edu bytes[i] = rem 7929537Satgutier@umich.edu if val == 0: 7939537Satgutier@umich.edu break 7949537Satgutier@umich.edu bytes[i - 1] += val 7959537Satgutier@umich.edu assert(bytes[0] <= 255) 7969537Satgutier@umich.edu return ':'.join(map(lambda x: '%02x' % x, bytes)) 7979537Satgutier@umich.edu 7989537Satgutier@umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 7999537Satgutier@umich.edudef NextEthernetAddr(): 8009537Satgutier@umich.edu global _NextEthernetAddr 8019537Satgutier@umich.edu 8029537Satgutier@umich.edu value = _NextEthernetAddr 8039537Satgutier@umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 8049537Satgutier@umich.edu return value 8059537Satgutier@umich.edu 8069537Satgutier@umich.educlass EthernetAddr(ParamValue): 8079537Satgutier@umich.edu cxx_type = 'Net::EthAddr' 8089537Satgutier@umich.edu ex_str = "00:90:00:00:00:01" 8099537Satgutier@umich.edu cmd_line_settable = True 8109537Satgutier@umich.edu 8119537Satgutier@umich.edu @classmethod 8129537Satgutier@umich.edu def cxx_predecls(cls, code): 8139537Satgutier@umich.edu code('#include "base/inet.hh"') 8149537Satgutier@umich.edu 8159537Satgutier@umich.edu @classmethod 8169537Satgutier@umich.edu def swig_predecls(cls, code): 8179537Satgutier@umich.edu code('%include "python/swig/inet.i"') 8189537Satgutier@umich.edu 8199537Satgutier@umich.edu def __init__(self, value): 8209537Satgutier@umich.edu if value == NextEthernetAddr: 8219537Satgutier@umich.edu self.value = value 8229537Satgutier@umich.edu return 8239537Satgutier@umich.edu 8249537Satgutier@umich.edu if not isinstance(value, str): 8259537Satgutier@umich.edu raise TypeError, "expected an ethernet address and didn't get one" 8269537Satgutier@umich.edu 8279537Satgutier@umich.edu bytes = value.split(':') 8289537Satgutier@umich.edu if len(bytes) != 6: 8299537Satgutier@umich.edu raise TypeError, 'invalid ethernet address %s' % value 8309537Satgutier@umich.edu 8319537Satgutier@umich.edu for byte in bytes: 8329537Satgutier@umich.edu if not 0 <= int(byte, base=16) <= 0xff: 8339537Satgutier@umich.edu raise TypeError, 'invalid ethernet address %s' % value 8349537Satgutier@umich.edu 8359537Satgutier@umich.edu self.value = value 8369537Satgutier@umich.edu 8379537Satgutier@umich.edu def __call__(self, value): 8389537Satgutier@umich.edu self.__init__(value) 8399537Satgutier@umich.edu return value 8409537Satgutier@umich.edu 8419537Satgutier@umich.edu def unproxy(self, base): 8429537Satgutier@umich.edu if self.value == NextEthernetAddr: 8439537Satgutier@umich.edu return EthernetAddr(self.value()) 8449537Satgutier@umich.edu return self 8459537Satgutier@umich.edu 8469537Satgutier@umich.edu def getValue(self): 8479537Satgutier@umich.edu from m5.internal.params import EthAddr 8489537Satgutier@umich.edu return EthAddr(self.value) 8499537Satgutier@umich.edu 8509537Satgutier@umich.edu def ini_str(self): 8519537Satgutier@umich.edu return self.value 8529537Satgutier@umich.edu 8539537Satgutier@umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of 8549537Satgutier@umich.edu# the form "a.b.c.d", or an integer representing an IP. 8559537Satgutier@umich.educlass IpAddress(ParamValue): 8569537Satgutier@umich.edu cxx_type = 'Net::IpAddress' 8579537Satgutier@umich.edu ex_str = "127.0.0.1" 8589537Satgutier@umich.edu cmd_line_settable = True 8599537Satgutier@umich.edu 8609537Satgutier@umich.edu @classmethod 8619537Satgutier@umich.edu def cxx_predecls(cls, code): 8629537Satgutier@umich.edu code('#include "base/inet.hh"') 8639537Satgutier@umich.edu 8649537Satgutier@umich.edu @classmethod 8659537Satgutier@umich.edu def swig_predecls(cls, code): 8669537Satgutier@umich.edu code('%include "python/swig/inet.i"') 8679537Satgutier@umich.edu 8689537Satgutier@umich.edu def __init__(self, value): 8699537Satgutier@umich.edu if isinstance(value, IpAddress): 8709537Satgutier@umich.edu self.ip = value.ip 8719537Satgutier@umich.edu else: 8729537Satgutier@umich.edu try: 8739537Satgutier@umich.edu self.ip = convert.toIpAddress(value) 8749537Satgutier@umich.edu except TypeError: 8759537Satgutier@umich.edu self.ip = long(value) 8769537Satgutier@umich.edu self.verifyIp() 8779537Satgutier@umich.edu 8789537Satgutier@umich.edu def __call__(self, value): 8799537Satgutier@umich.edu self.__init__(value) 8809537Satgutier@umich.edu return value 8819537Satgutier@umich.edu 8829537Satgutier@umich.edu def __str__(self): 8839537Satgutier@umich.edu tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)] 8849537Satgutier@umich.edu return '%d.%d.%d.%d' % tuple(tup) 8859537Satgutier@umich.edu 8869537Satgutier@umich.edu def __eq__(self, other): 8879537Satgutier@umich.edu if isinstance(other, IpAddress): 8889537Satgutier@umich.edu return self.ip == other.ip 8899537Satgutier@umich.edu elif isinstance(other, str): 8909537Satgutier@umich.edu try: 8919537Satgutier@umich.edu return self.ip == convert.toIpAddress(other) 8929537Satgutier@umich.edu except: 8939537Satgutier@umich.edu return False 8949537Satgutier@umich.edu else: 8959537Satgutier@umich.edu return self.ip == other 8969537Satgutier@umich.edu 8979537Satgutier@umich.edu def __ne__(self, other): 8989537Satgutier@umich.edu return not (self == other) 8999537Satgutier@umich.edu 9009537Satgutier@umich.edu def verifyIp(self): 9019537Satgutier@umich.edu if self.ip < 0 or self.ip >= (1 << 32): 9029537Satgutier@umich.edu raise TypeError, "invalid ip address %#08x" % self.ip 9039537Satgutier@umich.edu 9049537Satgutier@umich.edu def getValue(self): 9059537Satgutier@umich.edu from m5.internal.params import IpAddress 9069537Satgutier@umich.edu return IpAddress(self.ip) 9079537Satgutier@umich.edu 9089537Satgutier@umich.edu# When initializing an IpNetmask, pass in an existing IpNetmask, a string of 9099537Satgutier@umich.edu# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as 9109537Satgutier@umich.edu# positional or keyword arguments. 9119537Satgutier@umich.educlass IpNetmask(IpAddress): 9129537Satgutier@umich.edu cxx_type = 'Net::IpNetmask' 9139537Satgutier@umich.edu ex_str = "127.0.0.0/24" 9149537Satgutier@umich.edu cmd_line_settable = True 9159537Satgutier@umich.edu 9169537Satgutier@umich.edu @classmethod 9179537Satgutier@umich.edu def cxx_predecls(cls, code): 9189537Satgutier@umich.edu code('#include "base/inet.hh"') 9199537Satgutier@umich.edu 9209537Satgutier@umich.edu @classmethod 9219537Satgutier@umich.edu def swig_predecls(cls, code): 9229537Satgutier@umich.edu code('%include "python/swig/inet.i"') 9239537Satgutier@umich.edu 9249537Satgutier@umich.edu def __init__(self, *args, **kwargs): 9259537Satgutier@umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 9269537Satgutier@umich.edu if key in kwargs: 9279537Satgutier@umich.edu setattr(self, key, kwargs.pop(key)) 9289537Satgutier@umich.edu elif elseVal: 9299537Satgutier@umich.edu setattr(self, key, elseVal) 9309537Satgutier@umich.edu else: 9319537Satgutier@umich.edu raise TypeError, "No value set for %s" % key 9329537Satgutier@umich.edu 9339537Satgutier@umich.edu if len(args) == 0: 9349537Satgutier@umich.edu handle_kwarg(self, kwargs, 'ip') 9359537Satgutier@umich.edu handle_kwarg(self, kwargs, 'netmask') 9369537Satgutier@umich.edu 9379537Satgutier@umich.edu elif len(args) == 1: 9389537Satgutier@umich.edu if kwargs: 9399537Satgutier@umich.edu if not 'ip' in kwargs and not 'netmask' in kwargs: 9409537Satgutier@umich.edu raise TypeError, "Invalid arguments" 9419537Satgutier@umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 9429537Satgutier@umich.edu handle_kwarg(self, kwargs, 'netmask', args[0]) 9439537Satgutier@umich.edu elif isinstance(args[0], IpNetmask): 9449537Satgutier@umich.edu self.ip = args[0].ip 9459537Satgutier@umich.edu self.netmask = args[0].netmask 9469537Satgutier@umich.edu else: 9479537Satgutier@umich.edu (self.ip, self.netmask) = convert.toIpNetmask(args[0]) 9489537Satgutier@umich.edu 9499537Satgutier@umich.edu elif len(args) == 2: 9509537Satgutier@umich.edu self.ip = args[0] 9519537Satgutier@umich.edu self.netmask = args[1] 9529537Satgutier@umich.edu else: 9539537Satgutier@umich.edu raise TypeError, "Too many arguments specified" 9549537Satgutier@umich.edu 9559537Satgutier@umich.edu if kwargs: 9569537Satgutier@umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 9579537Satgutier@umich.edu 9589537Satgutier@umich.edu self.verify() 9599537Satgutier@umich.edu 9609537Satgutier@umich.edu def __call__(self, value): 9619537Satgutier@umich.edu self.__init__(value) 9629537Satgutier@umich.edu return value 9639537Satgutier@umich.edu 9649537Satgutier@umich.edu def __str__(self): 9659537Satgutier@umich.edu return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask) 9669537Satgutier@umich.edu 9679537Satgutier@umich.edu def __eq__(self, other): 9689537Satgutier@umich.edu if isinstance(other, IpNetmask): 9699537Satgutier@umich.edu return self.ip == other.ip and self.netmask == other.netmask 9709537Satgutier@umich.edu elif isinstance(other, str): 9719537Satgutier@umich.edu try: 9729537Satgutier@umich.edu return (self.ip, self.netmask) == convert.toIpNetmask(other) 9739537Satgutier@umich.edu except: 9749537Satgutier@umich.edu return False 9759537Satgutier@umich.edu else: 9769537Satgutier@umich.edu return False 9779537Satgutier@umich.edu 9789537Satgutier@umich.edu def verify(self): 9799537Satgutier@umich.edu self.verifyIp() 9809537Satgutier@umich.edu if self.netmask < 0 or self.netmask > 32: 9819537Satgutier@umich.edu raise TypeError, "invalid netmask %d" % netmask 9829537Satgutier@umich.edu 9839537Satgutier@umich.edu def getValue(self): 9849537Satgutier@umich.edu from m5.internal.params import IpNetmask 9859537Satgutier@umich.edu return IpNetmask(self.ip, self.netmask) 9869537Satgutier@umich.edu 9879537Satgutier@umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of 9889537Satgutier@umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments. 9899537Satgutier@umich.educlass IpWithPort(IpAddress): 9909537Satgutier@umich.edu cxx_type = 'Net::IpWithPort' 9919537Satgutier@umich.edu ex_str = "127.0.0.1:80" 9929537Satgutier@umich.edu cmd_line_settable = True 9939537Satgutier@umich.edu 9949537Satgutier@umich.edu @classmethod 9959537Satgutier@umich.edu def cxx_predecls(cls, code): 9969537Satgutier@umich.edu code('#include "base/inet.hh"') 9979537Satgutier@umich.edu 9989537Satgutier@umich.edu @classmethod 9999537Satgutier@umich.edu def swig_predecls(cls, code): 10009537Satgutier@umich.edu code('%include "python/swig/inet.i"') 10019537Satgutier@umich.edu 10029537Satgutier@umich.edu def __init__(self, *args, **kwargs): 10039537Satgutier@umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 10049537Satgutier@umich.edu if key in kwargs: 10059537Satgutier@umich.edu setattr(self, key, kwargs.pop(key)) 10069537Satgutier@umich.edu elif elseVal: 10079537Satgutier@umich.edu setattr(self, key, elseVal) 10089537Satgutier@umich.edu else: 10099537Satgutier@umich.edu raise TypeError, "No value set for %s" % key 10109537Satgutier@umich.edu 10119537Satgutier@umich.edu if len(args) == 0: 10129537Satgutier@umich.edu handle_kwarg(self, kwargs, 'ip') 10139537Satgutier@umich.edu handle_kwarg(self, kwargs, 'port') 10149537Satgutier@umich.edu 10159537Satgutier@umich.edu elif len(args) == 1: 10169537Satgutier@umich.edu if kwargs: 10179537Satgutier@umich.edu if not 'ip' in kwargs and not 'port' in kwargs: 10189537Satgutier@umich.edu raise TypeError, "Invalid arguments" 10199537Satgutier@umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 10209537Satgutier@umich.edu handle_kwarg(self, kwargs, 'port', args[0]) 10219537Satgutier@umich.edu elif isinstance(args[0], IpWithPort): 10229537Satgutier@umich.edu self.ip = args[0].ip 10239537Satgutier@umich.edu self.port = args[0].port 10249537Satgutier@umich.edu else: 10259537Satgutier@umich.edu (self.ip, self.port) = convert.toIpWithPort(args[0]) 10269537Satgutier@umich.edu 10279537Satgutier@umich.edu elif len(args) == 2: 10289537Satgutier@umich.edu self.ip = args[0] 10299537Satgutier@umich.edu self.port = args[1] 10309537Satgutier@umich.edu else: 10319537Satgutier@umich.edu raise TypeError, "Too many arguments specified" 10329537Satgutier@umich.edu 10339537Satgutier@umich.edu if kwargs: 10349537Satgutier@umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 10359537Satgutier@umich.edu 10369537Satgutier@umich.edu self.verify() 10379537Satgutier@umich.edu 10389537Satgutier@umich.edu def __call__(self, value): 10399537Satgutier@umich.edu self.__init__(value) 10409537Satgutier@umich.edu return value 10419537Satgutier@umich.edu 10429537Satgutier@umich.edu def __str__(self): 10439537Satgutier@umich.edu return "%s:%d" % (super(IpWithPort, self).__str__(), self.port) 10449537Satgutier@umich.edu 10459537Satgutier@umich.edu def __eq__(self, other): 10469537Satgutier@umich.edu if isinstance(other, IpWithPort): 10479537Satgutier@umich.edu return self.ip == other.ip and self.port == other.port 10489537Satgutier@umich.edu elif isinstance(other, str): 10499537Satgutier@umich.edu try: 10509537Satgutier@umich.edu return (self.ip, self.port) == convert.toIpWithPort(other) 10519537Satgutier@umich.edu except: 10529537Satgutier@umich.edu return False 10539537Satgutier@umich.edu else: 10549537Satgutier@umich.edu return False 10559537Satgutier@umich.edu 10569537Satgutier@umich.edu def verify(self): 10579537Satgutier@umich.edu self.verifyIp() 10589537Satgutier@umich.edu if self.port < 0 or self.port > 0xffff: 10599537Satgutier@umich.edu raise TypeError, "invalid port %d" % self.port 10609537Satgutier@umich.edu 10619537Satgutier@umich.edu def getValue(self): 10629537Satgutier@umich.edu from m5.internal.params import IpWithPort 10639537Satgutier@umich.edu return IpWithPort(self.ip, self.port) 10649537Satgutier@umich.edu 10659537Satgutier@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 10669537Satgutier@umich.edu "%a %b %d %H:%M:%S %Y", 10679537Satgutier@umich.edu "%Y/%m/%d %H:%M:%S", 10689537Satgutier@umich.edu "%Y/%m/%d %H:%M", 10699537Satgutier@umich.edu "%Y/%m/%d", 10709537Satgutier@umich.edu "%m/%d/%Y %H:%M:%S", 10719537Satgutier@umich.edu "%m/%d/%Y %H:%M", 10729537Satgutier@umich.edu "%m/%d/%Y", 10739537Satgutier@umich.edu "%m/%d/%y %H:%M:%S", 10749537Satgutier@umich.edu "%m/%d/%y %H:%M", 10759537Satgutier@umich.edu "%m/%d/%y"] 10769537Satgutier@umich.edu 10779537Satgutier@umich.edu 10789537Satgutier@umich.edudef parse_time(value): 10799537Satgutier@umich.edu from time import gmtime, strptime, struct_time, time 10809537Satgutier@umich.edu from datetime import datetime, date 10819537Satgutier@umich.edu 10829537Satgutier@umich.edu if isinstance(value, struct_time): 10839537Satgutier@umich.edu return value 10849537Satgutier@umich.edu 10859537Satgutier@umich.edu if isinstance(value, (int, long)): 10869537Satgutier@umich.edu return gmtime(value) 10879537Satgutier@umich.edu 10889537Satgutier@umich.edu if isinstance(value, (datetime, date)): 10899537Satgutier@umich.edu return value.timetuple() 10909537Satgutier@umich.edu 10919537Satgutier@umich.edu if isinstance(value, str): 10929537Satgutier@umich.edu if value in ('Now', 'Today'): 10939537Satgutier@umich.edu return time.gmtime(time.time()) 10949537Satgutier@umich.edu 10959537Satgutier@umich.edu for format in time_formats: 10969537Satgutier@umich.edu try: 10979537Satgutier@umich.edu return strptime(value, format) 10989537Satgutier@umich.edu except ValueError: 10999537Satgutier@umich.edu pass 11009537Satgutier@umich.edu 11019537Satgutier@umich.edu raise ValueError, "Could not parse '%s' as a time" % value 11029537Satgutier@umich.edu 11039537Satgutier@umich.educlass Time(ParamValue): 11049537Satgutier@umich.edu cxx_type = 'tm' 11059537Satgutier@umich.edu 11069537Satgutier@umich.edu @classmethod 11079537Satgutier@umich.edu def cxx_predecls(cls, code): 11089537Satgutier@umich.edu code('#include <time.h>') 11099537Satgutier@umich.edu 11109537Satgutier@umich.edu @classmethod 11119537Satgutier@umich.edu def swig_predecls(cls, code): 11129537Satgutier@umich.edu code('%include "python/swig/time.i"') 11139537Satgutier@umich.edu 11149537Satgutier@umich.edu def __init__(self, value): 11159537Satgutier@umich.edu self.value = parse_time(value) 11169537Satgutier@umich.edu 11179537Satgutier@umich.edu def __call__(self, value): 11189537Satgutier@umich.edu self.__init__(value) 11199537Satgutier@umich.edu return value 11209537Satgutier@umich.edu 11219537Satgutier@umich.edu def getValue(self): 11229537Satgutier@umich.edu from m5.internal.params import tm 11239537Satgutier@umich.edu 11249537Satgutier@umich.edu c_time = tm() 11259537Satgutier@umich.edu py_time = self.value 11269537Satgutier@umich.edu 11279537Satgutier@umich.edu # UNIX is years since 1900 11289537Satgutier@umich.edu c_time.tm_year = py_time.tm_year - 1900; 11299537Satgutier@umich.edu 11309537Satgutier@umich.edu # Python starts at 1, UNIX starts at 0 11319537Satgutier@umich.edu c_time.tm_mon = py_time.tm_mon - 1; 11329537Satgutier@umich.edu c_time.tm_mday = py_time.tm_mday; 11339537Satgutier@umich.edu c_time.tm_hour = py_time.tm_hour; 11349537Satgutier@umich.edu c_time.tm_min = py_time.tm_min; 11359537Satgutier@umich.edu c_time.tm_sec = py_time.tm_sec; 11369537Satgutier@umich.edu 11379537Satgutier@umich.edu # Python has 0 as Monday, UNIX is 0 as sunday 11389537Satgutier@umich.edu c_time.tm_wday = py_time.tm_wday + 1 11399537Satgutier@umich.edu if c_time.tm_wday > 6: 11409537Satgutier@umich.edu c_time.tm_wday -= 7; 11419537Satgutier@umich.edu 11429537Satgutier@umich.edu # Python starts at 1, Unix starts at 0 11439537Satgutier@umich.edu c_time.tm_yday = py_time.tm_yday - 1; 11449537Satgutier@umich.edu 11459537Satgutier@umich.edu return c_time 11469537Satgutier@umich.edu 11479537Satgutier@umich.edu def __str__(self): 11489537Satgutier@umich.edu return time.asctime(self.value) 11499537Satgutier@umich.edu 11509537Satgutier@umich.edu def ini_str(self): 11519537Satgutier@umich.edu return str(self) 11529537Satgutier@umich.edu 11539537Satgutier@umich.edu def get_config_as_dict(self): 11549537Satgutier@umich.edu assert false 11559537Satgutier@umich.edu return str(self) 11569537Satgutier@umich.edu 11579537Satgutier@umich.edu# Enumerated types are a little more complex. The user specifies the 11589537Satgutier@umich.edu# type as Enum(foo) where foo is either a list or dictionary of 11599537Satgutier@umich.edu# alternatives (typically strings, but not necessarily so). (In the 11609537Satgutier@umich.edu# long run, the integer value of the parameter will be the list index 11619537Satgutier@umich.edu# or the corresponding dictionary value. For now, since we only check 11629537Satgutier@umich.edu# that the alternative is valid and then spit it into a .ini file, 11639537Satgutier@umich.edu# there's not much point in using the dictionary.) 11649537Satgutier@umich.edu 11659537Satgutier@umich.edu# What Enum() must do is generate a new type encapsulating the 11669537Satgutier@umich.edu# provided list/dictionary so that specific values of the parameter 11679537Satgutier@umich.edu# can be instances of that type. We define two hidden internal 11689537Satgutier@umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then 11699537Satgutier@umich.edu# derive the new type from the appropriate base class on the fly. 11709537Satgutier@umich.edu 11719537Satgutier@umich.eduallEnums = {} 11729537Satgutier@umich.edu# Metaclass for Enum types 11739537Satgutier@umich.educlass MetaEnum(MetaParamValue): 11749537Satgutier@umich.edu def __new__(mcls, name, bases, dict): 11759537Satgutier@umich.edu assert name not in allEnums 11769537Satgutier@umich.edu 11779537Satgutier@umich.edu cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 11789537Satgutier@umich.edu allEnums[name] = cls 11799537Satgutier@umich.edu return cls 11809537Satgutier@umich.edu 11819537Satgutier@umich.edu def __init__(cls, name, bases, init_dict): 11829537Satgutier@umich.edu if init_dict.has_key('map'): 11839537Satgutier@umich.edu if not isinstance(cls.map, dict): 11849537Satgutier@umich.edu raise TypeError, "Enum-derived class attribute 'map' " \ 11859537Satgutier@umich.edu "must be of type dict" 11869537Satgutier@umich.edu # build list of value strings from map 11879537Satgutier@umich.edu cls.vals = cls.map.keys() 11889537Satgutier@umich.edu cls.vals.sort() 11899537Satgutier@umich.edu elif init_dict.has_key('vals'): 11909537Satgutier@umich.edu if not isinstance(cls.vals, list): 11919537Satgutier@umich.edu raise TypeError, "Enum-derived class attribute 'vals' " \ 11929537Satgutier@umich.edu "must be of type list" 11939537Satgutier@umich.edu # build string->value map from vals sequence 11949537Satgutier@umich.edu cls.map = {} 11959537Satgutier@umich.edu for idx,val in enumerate(cls.vals): 11969537Satgutier@umich.edu cls.map[val] = idx 11979537Satgutier@umich.edu else: 11989537Satgutier@umich.edu raise TypeError, "Enum-derived class must define "\ 11999537Satgutier@umich.edu "attribute 'map' or 'vals'" 12009537Satgutier@umich.edu 12019537Satgutier@umich.edu cls.cxx_type = 'Enums::%s' % name 12029537Satgutier@umich.edu 12039537Satgutier@umich.edu super(MetaEnum, cls).__init__(name, bases, init_dict) 12049537Satgutier@umich.edu 12059537Satgutier@umich.edu # Generate C++ class declaration for this enum type. 12069537Satgutier@umich.edu # Note that we wrap the enum in a class/struct to act as a namespace, 12079537Satgutier@umich.edu # so that the enum strings can be brief w/o worrying about collisions. 12089537Satgutier@umich.edu def cxx_decl(cls, code): 12099537Satgutier@umich.edu wrapper_name = cls.wrapper_name 12109537Satgutier@umich.edu wrapper = 'struct' if cls.wrapper_is_struct else 'namespace' 12119537Satgutier@umich.edu name = cls.__name__ if cls.enum_name is None else cls.enum_name 12129537Satgutier@umich.edu idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name) 12139537Satgutier@umich.edu 12149537Satgutier@umich.edu code('''\ 12159537Satgutier@umich.edu#ifndef $idem_macro 12169537Satgutier@umich.edu#define $idem_macro 12179537Satgutier@umich.edu 12189537Satgutier@umich.edu$wrapper $wrapper_name { 12199537Satgutier@umich.edu enum $name { 12209537Satgutier@umich.edu''') 12219537Satgutier@umich.edu code.indent(2) 12229537Satgutier@umich.edu for val in cls.vals: 12239537Satgutier@umich.edu code('$val = ${{cls.map[val]}},') 12249537Satgutier@umich.edu code('Num_$name = ${{len(cls.vals)}}') 12259537Satgutier@umich.edu code.dedent(2) 12269537Satgutier@umich.edu code(' };') 12279537Satgutier@umich.edu 12289537Satgutier@umich.edu if cls.wrapper_is_struct: 12299537Satgutier@umich.edu code(' static const char *${name}Strings[Num_${name}];') 12309537Satgutier@umich.edu code('};') 12319537Satgutier@umich.edu else: 12329537Satgutier@umich.edu code('extern const char *${name}Strings[Num_${name}];') 12339537Satgutier@umich.edu code('}') 12349537Satgutier@umich.edu 12359537Satgutier@umich.edu code() 12369537Satgutier@umich.edu code('#endif // $idem_macro') 12379537Satgutier@umich.edu 12389537Satgutier@umich.edu def cxx_def(cls, code): 12399537Satgutier@umich.edu wrapper_name = cls.wrapper_name 12409537Satgutier@umich.edu file_name = cls.__name__ 12419537Satgutier@umich.edu name = cls.__name__ if cls.enum_name is None else cls.enum_name 12429537Satgutier@umich.edu 12439537Satgutier@umich.edu code('#include "enums/$file_name.hh"') 12449537Satgutier@umich.edu if cls.wrapper_is_struct: 12459537Satgutier@umich.edu code('const char *${wrapper_name}::${name}Strings' 12469537Satgutier@umich.edu '[Num_${name}] =') 12479537Satgutier@umich.edu else: 12489537Satgutier@umich.edu code('namespace Enums {') 12499537Satgutier@umich.edu code.indent(1) 12509537Satgutier@umich.edu code(' const char *${name}Strings[Num_${name}] =') 12519537Satgutier@umich.edu 12529537Satgutier@umich.edu code('{') 12539537Satgutier@umich.edu code.indent(1) 12549537Satgutier@umich.edu for val in cls.vals: 12559537Satgutier@umich.edu code('"$val",') 12569537Satgutier@umich.edu code.dedent(1) 12579537Satgutier@umich.edu code('};') 12589537Satgutier@umich.edu 12599537Satgutier@umich.edu if not cls.wrapper_is_struct: 12609537Satgutier@umich.edu code('} // namespace $wrapper_name') 12619537Satgutier@umich.edu code.dedent(1) 12629537Satgutier@umich.edu 12639537Satgutier@umich.edu def swig_decl(cls, code): 12649537Satgutier@umich.edu name = cls.__name__ 12659537Satgutier@umich.edu code('''\ 12669537Satgutier@umich.edu%module(package="m5.internal") enum_$name 12679537Satgutier@umich.edu 12689537Satgutier@umich.edu%{ 12699537Satgutier@umich.edu#include "enums/$name.hh" 12709537Satgutier@umich.edu%} 12719537Satgutier@umich.edu 12729537Satgutier@umich.edu%include "enums/$name.hh" 12739537Satgutier@umich.edu''') 12749537Satgutier@umich.edu 12759537Satgutier@umich.edu 12769537Satgutier@umich.edu# Base class for enum types. 12779537Satgutier@umich.educlass Enum(ParamValue): 12789537Satgutier@umich.edu __metaclass__ = MetaEnum 12799537Satgutier@umich.edu vals = [] 12809537Satgutier@umich.edu cmd_line_settable = True 12819537Satgutier@umich.edu 12829537Satgutier@umich.edu # The name of the wrapping namespace or struct 12839537Satgutier@umich.edu wrapper_name = 'Enums' 12849537Satgutier@umich.edu 12859537Satgutier@umich.edu # If true, the enum is wrapped in a struct rather than a namespace 12869537Satgutier@umich.edu wrapper_is_struct = False 12879537Satgutier@umich.edu 12889537Satgutier@umich.edu # If not None, use this as the enum name rather than this class name 12899537Satgutier@umich.edu enum_name = None 12909537Satgutier@umich.edu 12919537Satgutier@umich.edu def __init__(self, value): 12929537Satgutier@umich.edu if value not in self.map: 12939537Satgutier@umich.edu raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 12949537Satgutier@umich.edu % (value, self.vals) 12959537Satgutier@umich.edu self.value = value 12969537Satgutier@umich.edu 12979537Satgutier@umich.edu def __call__(self, value): 12989537Satgutier@umich.edu self.__init__(value) 12999537Satgutier@umich.edu return value 13009537Satgutier@umich.edu 13019537Satgutier@umich.edu @classmethod 13029537Satgutier@umich.edu def cxx_predecls(cls, code): 13039537Satgutier@umich.edu code('#include "enums/$0.hh"', cls.__name__) 13049537Satgutier@umich.edu 13059537Satgutier@umich.edu @classmethod 13069537Satgutier@umich.edu def swig_predecls(cls, code): 13079537Satgutier@umich.edu code('%import "python/m5/internal/enum_$0.i"', cls.__name__) 13089537Satgutier@umich.edu 13099537Satgutier@umich.edu def getValue(self): 13109537Satgutier@umich.edu return int(self.map[self.value]) 13119537Satgutier@umich.edu 13129537Satgutier@umich.edu def __str__(self): 13139537Satgutier@umich.edu return self.value 13149537Satgutier@umich.edu 13159537Satgutier@umich.edu# how big does a rounding error need to be before we warn about it? 13169537Satgutier@umich.edufrequency_tolerance = 0.001 # 0.1% 13179537Satgutier@umich.edu 13189537Satgutier@umich.educlass TickParamValue(NumericParamValue): 13199537Satgutier@umich.edu cxx_type = 'Tick' 13209537Satgutier@umich.edu ex_str = "1MHz" 13219537Satgutier@umich.edu cmd_line_settable = True 13229537Satgutier@umich.edu 13239537Satgutier@umich.edu @classmethod 13249537Satgutier@umich.edu def cxx_predecls(cls, code): 13259537Satgutier@umich.edu code('#include "base/types.hh"') 13269537Satgutier@umich.edu 13279537Satgutier@umich.edu @classmethod 13289537Satgutier@umich.edu def swig_predecls(cls, code): 13299537Satgutier@umich.edu code('%import "stdint.i"') 13309537Satgutier@umich.edu code('%import "base/types.hh"') 13319537Satgutier@umich.edu 13329537Satgutier@umich.edu def __call__(self, value): 13339537Satgutier@umich.edu self.__init__(value) 13349537Satgutier@umich.edu return value 13359537Satgutier@umich.edu 13369537Satgutier@umich.edu def getValue(self): 13379537Satgutier@umich.edu return long(self.value) 13389537Satgutier@umich.edu 13399537Satgutier@umich.educlass Latency(TickParamValue): 13409537Satgutier@umich.edu ex_str = "100ns" 13419537Satgutier@umich.edu 13429537Satgutier@umich.edu def __init__(self, value): 13439537Satgutier@umich.edu if isinstance(value, (Latency, Clock)): 13449537Satgutier@umich.edu self.ticks = value.ticks 13459537Satgutier@umich.edu self.value = value.value 13469537Satgutier@umich.edu elif isinstance(value, Frequency): 13479537Satgutier@umich.edu self.ticks = value.ticks 13489537Satgutier@umich.edu self.value = 1.0 / value.value 13499537Satgutier@umich.edu elif value.endswith('t'): 13509537Satgutier@umich.edu self.ticks = True 13519537Satgutier@umich.edu self.value = int(value[:-1]) 13529537Satgutier@umich.edu else: 13539537Satgutier@umich.edu self.ticks = False 13549537Satgutier@umich.edu self.value = convert.toLatency(value) 13559537Satgutier@umich.edu 13569537Satgutier@umich.edu def __call__(self, value): 13579537Satgutier@umich.edu self.__init__(value) 13589537Satgutier@umich.edu return value 13599537Satgutier@umich.edu 13609537Satgutier@umich.edu def __getattr__(self, attr): 13619537Satgutier@umich.edu if attr in ('latency', 'period'): 13629537Satgutier@umich.edu return self 13639537Satgutier@umich.edu if attr == 'frequency': 13649537Satgutier@umich.edu return Frequency(self) 13659537Satgutier@umich.edu raise AttributeError, "Latency object has no attribute '%s'" % attr 13669537Satgutier@umich.edu 13679537Satgutier@umich.edu def getValue(self): 13689537Satgutier@umich.edu if self.ticks or self.value == 0: 13699537Satgutier@umich.edu value = self.value 13709537Satgutier@umich.edu else: 13719537Satgutier@umich.edu value = ticks.fromSeconds(self.value) 13729537Satgutier@umich.edu return long(value) 13739537Satgutier@umich.edu 13749537Satgutier@umich.edu def config_value(self): 13759537Satgutier@umich.edu return self.getValue() 13769537Satgutier@umich.edu 13779537Satgutier@umich.edu # convert latency to ticks 13789537Satgutier@umich.edu def ini_str(self): 13799537Satgutier@umich.edu return '%d' % self.getValue() 13809537Satgutier@umich.edu 13819537Satgutier@umich.educlass Frequency(TickParamValue): 13829537Satgutier@umich.edu ex_str = "1GHz" 13839537Satgutier@umich.edu 13849537Satgutier@umich.edu def __init__(self, value): 13859537Satgutier@umich.edu if isinstance(value, (Latency, Clock)): 13869537Satgutier@umich.edu if value.value == 0: 13879537Satgutier@umich.edu self.value = 0 13889537Satgutier@umich.edu else: 13899537Satgutier@umich.edu self.value = 1.0 / value.value 13909537Satgutier@umich.edu self.ticks = value.ticks 13919537Satgutier@umich.edu elif isinstance(value, Frequency): 13929537Satgutier@umich.edu self.value = value.value 13939537Satgutier@umich.edu self.ticks = value.ticks 13949537Satgutier@umich.edu else: 13959537Satgutier@umich.edu self.ticks = False 13969537Satgutier@umich.edu self.value = convert.toFrequency(value) 13979537Satgutier@umich.edu 13989537Satgutier@umich.edu def __call__(self, value): 13999537Satgutier@umich.edu self.__init__(value) 14009537Satgutier@umich.edu return value 14019537Satgutier@umich.edu 14029537Satgutier@umich.edu def __getattr__(self, attr): 14039537Satgutier@umich.edu if attr == 'frequency': 14049537Satgutier@umich.edu return self 14059537Satgutier@umich.edu if attr in ('latency', 'period'): 14069537Satgutier@umich.edu return Latency(self) 14079537Satgutier@umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 14089537Satgutier@umich.edu 14099537Satgutier@umich.edu # convert latency to ticks 14109537Satgutier@umich.edu def getValue(self): 14119537Satgutier@umich.edu if self.ticks or self.value == 0: 14129537Satgutier@umich.edu value = self.value 14139537Satgutier@umich.edu else: 14149537Satgutier@umich.edu value = ticks.fromSeconds(1.0 / self.value) 14159537Satgutier@umich.edu return long(value) 14169537Satgutier@umich.edu 14179537Satgutier@umich.edu def config_value(self): 14189537Satgutier@umich.edu return self.getValue() 14199537Satgutier@umich.edu 14209537Satgutier@umich.edu def ini_str(self): 14219537Satgutier@umich.edu return '%d' % self.getValue() 14229537Satgutier@umich.edu 14239537Satgutier@umich.edu# A generic Frequency and/or Latency value. Value is stored as a 14249537Satgutier@umich.edu# latency, just like Latency and Frequency. 14259537Satgutier@umich.educlass Clock(TickParamValue): 14269537Satgutier@umich.edu def __init__(self, value): 14279537Satgutier@umich.edu if isinstance(value, (Latency, Clock)): 14289537Satgutier@umich.edu self.ticks = value.ticks 14299537Satgutier@umich.edu self.value = value.value 14309537Satgutier@umich.edu elif isinstance(value, Frequency): 14319537Satgutier@umich.edu self.ticks = value.ticks 14329537Satgutier@umich.edu self.value = 1.0 / value.value 14339537Satgutier@umich.edu elif value.endswith('t'): 14349537Satgutier@umich.edu self.ticks = True 14359537Satgutier@umich.edu self.value = int(value[:-1]) 14369537Satgutier@umich.edu else: 14379537Satgutier@umich.edu self.ticks = False 14389537Satgutier@umich.edu self.value = convert.anyToLatency(value) 14399537Satgutier@umich.edu 14409537Satgutier@umich.edu def __call__(self, value): 14419537Satgutier@umich.edu self.__init__(value) 14429537Satgutier@umich.edu return value 14439537Satgutier@umich.edu 14449537Satgutier@umich.edu def __str__(self): 14459537Satgutier@umich.edu return "%s" % Latency(self) 14469537Satgutier@umich.edu 14479537Satgutier@umich.edu def __getattr__(self, attr): 14489537Satgutier@umich.edu if attr == 'frequency': 14499537Satgutier@umich.edu return Frequency(self) 14509537Satgutier@umich.edu if attr in ('latency', 'period'): 14519537Satgutier@umich.edu return Latency(self) 14529537Satgutier@umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 14539537Satgutier@umich.edu 14549537Satgutier@umich.edu def getValue(self): 14559537Satgutier@umich.edu return self.period.getValue() 14569537Satgutier@umich.edu 14579537Satgutier@umich.edu def config_value(self): 14589537Satgutier@umich.edu return self.period.config_value() 14599537Satgutier@umich.edu 14609537Satgutier@umich.edu def ini_str(self): 14619537Satgutier@umich.edu return self.period.ini_str() 14629537Satgutier@umich.edu 14639537Satgutier@umich.educlass Voltage(float,ParamValue): 14649537Satgutier@umich.edu cxx_type = 'double' 14659537Satgutier@umich.edu ex_str = "1V" 14669537Satgutier@umich.edu cmd_line_settable = False 1467 1468 def __new__(cls, value): 1469 # convert to voltage 1470 val = convert.toVoltage(value) 1471 return super(cls, Voltage).__new__(cls, val) 1472 1473 def __call__(self, value): 1474 val = convert.toVoltage(value) 1475 self.__init__(val) 1476 return value 1477 1478 def __str__(self): 1479 return str(self.getValue()) 1480 1481 def getValue(self): 1482 value = float(self) 1483 return value 1484 1485 def ini_str(self): 1486 return '%f' % self.getValue() 1487 1488class NetworkBandwidth(float,ParamValue): 1489 cxx_type = 'float' 1490 ex_str = "1Gbps" 1491 cmd_line_settable = True 1492 1493 def __new__(cls, value): 1494 # convert to bits per second 1495 val = convert.toNetworkBandwidth(value) 1496 return super(cls, NetworkBandwidth).__new__(cls, val) 1497 1498 def __str__(self): 1499 return str(self.val) 1500 1501 def __call__(self, value): 1502 val = convert.toNetworkBandwidth(value) 1503 self.__init__(val) 1504 return value 1505 1506 def getValue(self): 1507 # convert to seconds per byte 1508 value = 8.0 / float(self) 1509 # convert to ticks per byte 1510 value = ticks.fromSeconds(value) 1511 return float(value) 1512 1513 def ini_str(self): 1514 return '%f' % self.getValue() 1515 1516 def config_value(self): 1517 return '%f' % self.getValue() 1518 1519class MemoryBandwidth(float,ParamValue): 1520 cxx_type = 'float' 1521 ex_str = "1GB/s" 1522 cmd_line_settable = True 1523 1524 def __new__(cls, value): 1525 # convert to bytes per second 1526 val = convert.toMemoryBandwidth(value) 1527 return super(cls, MemoryBandwidth).__new__(cls, val) 1528 1529 def __call__(self, value): 1530 val = convert.toMemoryBandwidth(value) 1531 self.__init__(val) 1532 return value 1533 1534 def getValue(self): 1535 # convert to seconds per byte 1536 value = float(self) 1537 if value: 1538 value = 1.0 / float(self) 1539 # convert to ticks per byte 1540 value = ticks.fromSeconds(value) 1541 return float(value) 1542 1543 def ini_str(self): 1544 return '%f' % self.getValue() 1545 1546 def config_value(self): 1547 return '%f' % self.getValue() 1548 1549# 1550# "Constants"... handy aliases for various values. 1551# 1552 1553# Special class for NULL pointers. Note the special check in 1554# make_param_value() above that lets these be assigned where a 1555# SimObject is required. 1556# only one copy of a particular node 1557class NullSimObject(object): 1558 __metaclass__ = Singleton 1559 1560 def __call__(cls): 1561 return cls 1562 1563 def _instantiate(self, parent = None, path = ''): 1564 pass 1565 1566 def ini_str(self): 1567 return 'Null' 1568 1569 def unproxy(self, base): 1570 return self 1571 1572 def set_path(self, parent, name): 1573 pass 1574 1575 def __str__(self): 1576 return 'Null' 1577 1578 def config_value(self): 1579 return None 1580 1581 def getValue(self): 1582 return None 1583 1584# The only instance you'll ever need... 1585NULL = NullSimObject() 1586 1587def isNullPointer(value): 1588 return isinstance(value, NullSimObject) 1589 1590# Some memory range specifications use this as a default upper bound. 1591MaxAddr = Addr.max 1592MaxTick = Tick.max 1593AllMemory = AddrRange(0, MaxAddr) 1594 1595 1596##################################################################### 1597# 1598# Port objects 1599# 1600# Ports are used to interconnect objects in the memory system. 1601# 1602##################################################################### 1603 1604# Port reference: encapsulates a reference to a particular port on a 1605# particular SimObject. 1606class PortRef(object): 1607 def __init__(self, simobj, name, role): 1608 assert(isSimObject(simobj) or isSimObjectClass(simobj)) 1609 self.simobj = simobj 1610 self.name = name 1611 self.role = role 1612 self.peer = None # not associated with another port yet 1613 self.ccConnected = False # C++ port connection done? 1614 self.index = -1 # always -1 for non-vector ports 1615 1616 def __str__(self): 1617 return '%s.%s' % (self.simobj, self.name) 1618 1619 def __len__(self): 1620 # Return the number of connected ports, i.e. 0 is we have no 1621 # peer and 1 if we do. 1622 return int(self.peer != None) 1623 1624 # for config.ini, print peer's name (not ours) 1625 def ini_str(self): 1626 return str(self.peer) 1627 1628 # for config.json 1629 def get_config_as_dict(self): 1630 return {'role' : self.role, 'peer' : str(self.peer)} 1631 1632 def __getattr__(self, attr): 1633 if attr == 'peerObj': 1634 # shorthand for proxies 1635 return self.peer.simobj 1636 raise AttributeError, "'%s' object has no attribute '%s'" % \ 1637 (self.__class__.__name__, attr) 1638 1639 # Full connection is symmetric (both ways). Called via 1640 # SimObject.__setattr__ as a result of a port assignment, e.g., 1641 # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 1642 # e.g., "obj1.portA[3] = obj2.portB". 1643 def connect(self, other): 1644 if isinstance(other, VectorPortRef): 1645 # reference to plain VectorPort is implicit append 1646 other = other._get_next() 1647 if self.peer and not proxy.isproxy(self.peer): 1648 fatal("Port %s is already connected to %s, cannot connect %s\n", 1649 self, self.peer, other); 1650 self.peer = other 1651 if proxy.isproxy(other): 1652 other.set_param_desc(PortParamDesc()) 1653 elif isinstance(other, PortRef): 1654 if other.peer is not self: 1655 other.connect(self) 1656 else: 1657 raise TypeError, \ 1658 "assigning non-port reference '%s' to port '%s'" \ 1659 % (other, self) 1660 1661 # Allow a master/slave port pair to be spliced between 1662 # a port and its connected peer. Useful operation for connecting 1663 # instrumentation structures into a system when it is necessary 1664 # to connect the instrumentation after the full system has been 1665 # constructed. 1666 def splice(self, new_master_peer, new_slave_peer): 1667 if self.peer and not proxy.isproxy(self.peer): 1668 if isinstance(new_master_peer, PortRef) and \ 1669 isinstance(new_slave_peer, PortRef): 1670 old_peer = self.peer 1671 if self.role == 'SLAVE': 1672 self.peer = new_master_peer 1673 old_peer.peer = new_slave_peer 1674 new_master_peer.connect(self) 1675 new_slave_peer.connect(old_peer) 1676 elif self.role == 'MASTER': 1677 self.peer = new_slave_peer 1678 old_peer.peer = new_master_peer 1679 new_slave_peer.connect(self) 1680 new_master_peer.connect(old_peer) 1681 else: 1682 panic("Port %s has unknown role, "+\ 1683 "cannot splice in new peers\n", self) 1684 else: 1685 raise TypeError, \ 1686 "Splicing non-port references '%s','%s' to port '%s'"\ 1687 % (new_peer, peers_new_peer, self) 1688 else: 1689 fatal("Port %s not connected, cannot splice in new peers\n", self) 1690 1691 def clone(self, simobj, memo): 1692 if memo.has_key(self): 1693 return memo[self] 1694 newRef = copy.copy(self) 1695 memo[self] = newRef 1696 newRef.simobj = simobj 1697 assert(isSimObject(newRef.simobj)) 1698 if self.peer and not proxy.isproxy(self.peer): 1699 peerObj = self.peer.simobj(_memo=memo) 1700 newRef.peer = self.peer.clone(peerObj, memo) 1701 assert(not isinstance(newRef.peer, VectorPortRef)) 1702 return newRef 1703 1704 def unproxy(self, simobj): 1705 assert(simobj is self.simobj) 1706 if proxy.isproxy(self.peer): 1707 try: 1708 realPeer = self.peer.unproxy(self.simobj) 1709 except: 1710 print "Error in unproxying port '%s' of %s" % \ 1711 (self.name, self.simobj.path()) 1712 raise 1713 self.connect(realPeer) 1714 1715 # Call C++ to create corresponding port connection between C++ objects 1716 def ccConnect(self): 1717 from m5.internal.pyobject import connectPorts 1718 1719 if self.role == 'SLAVE': 1720 # do nothing and let the master take care of it 1721 return 1722 1723 if self.ccConnected: # already done this 1724 return 1725 peer = self.peer 1726 if not self.peer: # nothing to connect to 1727 return 1728 1729 # check that we connect a master to a slave 1730 if self.role == peer.role: 1731 raise TypeError, \ 1732 "cannot connect '%s' and '%s' due to identical role '%s'" \ 1733 % (peer, self, self.role) 1734 1735 try: 1736 # self is always the master and peer the slave 1737 connectPorts(self.simobj.getCCObject(), self.name, self.index, 1738 peer.simobj.getCCObject(), peer.name, peer.index) 1739 except: 1740 print "Error connecting port %s.%s to %s.%s" % \ 1741 (self.simobj.path(), self.name, 1742 peer.simobj.path(), peer.name) 1743 raise 1744 self.ccConnected = True 1745 peer.ccConnected = True 1746 1747# A reference to an individual element of a VectorPort... much like a 1748# PortRef, but has an index. 1749class VectorPortElementRef(PortRef): 1750 def __init__(self, simobj, name, role, index): 1751 PortRef.__init__(self, simobj, name, role) 1752 self.index = index 1753 1754 def __str__(self): 1755 return '%s.%s[%d]' % (self.simobj, self.name, self.index) 1756 1757# A reference to a complete vector-valued port (not just a single element). 1758# Can be indexed to retrieve individual VectorPortElementRef instances. 1759class VectorPortRef(object): 1760 def __init__(self, simobj, name, role): 1761 assert(isSimObject(simobj) or isSimObjectClass(simobj)) 1762 self.simobj = simobj 1763 self.name = name 1764 self.role = role 1765 self.elements = [] 1766 1767 def __str__(self): 1768 return '%s.%s[:]' % (self.simobj, self.name) 1769 1770 def __len__(self): 1771 # Return the number of connected peers, corresponding the the 1772 # length of the elements. 1773 return len(self.elements) 1774 1775 # for config.ini, print peer's name (not ours) 1776 def ini_str(self): 1777 return ' '.join([el.ini_str() for el in self.elements]) 1778 1779 # for config.json 1780 def get_config_as_dict(self): 1781 return {'role' : self.role, 1782 'peer' : [el.ini_str() for el in self.elements]} 1783 1784 def __getitem__(self, key): 1785 if not isinstance(key, int): 1786 raise TypeError, "VectorPort index must be integer" 1787 if key >= len(self.elements): 1788 # need to extend list 1789 ext = [VectorPortElementRef(self.simobj, self.name, self.role, i) 1790 for i in range(len(self.elements), key+1)] 1791 self.elements.extend(ext) 1792 return self.elements[key] 1793 1794 def _get_next(self): 1795 return self[len(self.elements)] 1796 1797 def __setitem__(self, key, value): 1798 if not isinstance(key, int): 1799 raise TypeError, "VectorPort index must be integer" 1800 self[key].connect(value) 1801 1802 def connect(self, other): 1803 if isinstance(other, (list, tuple)): 1804 # Assign list of port refs to vector port. 1805 # For now, append them... not sure if that's the right semantics 1806 # or if it should replace the current vector. 1807 for ref in other: 1808 self._get_next().connect(ref) 1809 else: 1810 # scalar assignment to plain VectorPort is implicit append 1811 self._get_next().connect(other) 1812 1813 def clone(self, simobj, memo): 1814 if memo.has_key(self): 1815 return memo[self] 1816 newRef = copy.copy(self) 1817 memo[self] = newRef 1818 newRef.simobj = simobj 1819 assert(isSimObject(newRef.simobj)) 1820 newRef.elements = [el.clone(simobj, memo) for el in self.elements] 1821 return newRef 1822 1823 def unproxy(self, simobj): 1824 [el.unproxy(simobj) for el in self.elements] 1825 1826 def ccConnect(self): 1827 [el.ccConnect() for el in self.elements] 1828 1829# Port description object. Like a ParamDesc object, this represents a 1830# logical port in the SimObject class, not a particular port on a 1831# SimObject instance. The latter are represented by PortRef objects. 1832class Port(object): 1833 # Generate a PortRef for this port on the given SimObject with the 1834 # given name 1835 def makeRef(self, simobj): 1836 return PortRef(simobj, self.name, self.role) 1837 1838 # Connect an instance of this port (on the given SimObject with 1839 # the given name) with the port described by the supplied PortRef 1840 def connect(self, simobj, ref): 1841 self.makeRef(simobj).connect(ref) 1842 1843 # No need for any pre-declarations at the moment as we merely rely 1844 # on an unsigned int. 1845 def cxx_predecls(self, code): 1846 pass 1847 1848 # Declare an unsigned int with the same name as the port, that 1849 # will eventually hold the number of connected ports (and thus the 1850 # number of elements for a VectorPort). 1851 def cxx_decl(self, code): 1852 code('unsigned int port_${{self.name}}_connection_count;') 1853 1854class MasterPort(Port): 1855 # MasterPort("description") 1856 def __init__(self, *args): 1857 if len(args) == 1: 1858 self.desc = args[0] 1859 self.role = 'MASTER' 1860 else: 1861 raise TypeError, 'wrong number of arguments' 1862 1863class SlavePort(Port): 1864 # SlavePort("description") 1865 def __init__(self, *args): 1866 if len(args) == 1: 1867 self.desc = args[0] 1868 self.role = 'SLAVE' 1869 else: 1870 raise TypeError, 'wrong number of arguments' 1871 1872# VectorPort description object. Like Port, but represents a vector 1873# of connections (e.g., as on a XBar). 1874class VectorPort(Port): 1875 def __init__(self, *args): 1876 self.isVec = True 1877 1878 def makeRef(self, simobj): 1879 return VectorPortRef(simobj, self.name, self.role) 1880 1881class VectorMasterPort(VectorPort): 1882 # VectorMasterPort("description") 1883 def __init__(self, *args): 1884 if len(args) == 1: 1885 self.desc = args[0] 1886 self.role = 'MASTER' 1887 VectorPort.__init__(self, *args) 1888 else: 1889 raise TypeError, 'wrong number of arguments' 1890 1891class VectorSlavePort(VectorPort): 1892 # VectorSlavePort("description") 1893 def __init__(self, *args): 1894 if len(args) == 1: 1895 self.desc = args[0] 1896 self.role = 'SLAVE' 1897 VectorPort.__init__(self, *args) 1898 else: 1899 raise TypeError, 'wrong number of arguments' 1900 1901# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 1902# proxy objects (via set_param_desc()) so that proxy error messages 1903# make sense. 1904class PortParamDesc(object): 1905 __metaclass__ = Singleton 1906 1907 ptype_str = 'Port' 1908 ptype = Port 1909 1910baseEnums = allEnums.copy() 1911baseParams = allParams.copy() 1912 1913def clear(): 1914 global allEnums, allParams 1915 1916 allEnums = baseEnums.copy() 1917 allParams = baseParams.copy() 1918 1919__all__ = ['Param', 'VectorParam', 1920 'Enum', 'Bool', 'String', 'Float', 1921 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 1922 'Int32', 'UInt32', 'Int64', 'UInt64', 1923 'Counter', 'Addr', 'Tick', 'Percent', 1924 'TcpPort', 'UdpPort', 'EthernetAddr', 1925 'IpAddress', 'IpNetmask', 'IpWithPort', 1926 'MemorySize', 'MemorySize32', 1927 'Latency', 'Frequency', 'Clock', 'Voltage', 1928 'NetworkBandwidth', 'MemoryBandwidth', 1929 'AddrRange', 1930 'MaxAddr', 'MaxTick', 'AllMemory', 1931 'Time', 1932 'NextEthernetAddr', 'NULL', 1933 'MasterPort', 'SlavePort', 1934 'VectorMasterPort', 'VectorSlavePort'] 1935 1936import SimObject 1937