params.py revision 10201
19544Sandreas.hansson@arm.com# Copyright (c) 2012-2013 ARM Limited 28839Sandreas.hansson@arm.com# All rights reserved. 38839Sandreas.hansson@arm.com# 48839Sandreas.hansson@arm.com# The license below extends only to copyright in the software and shall 58839Sandreas.hansson@arm.com# not be construed as granting a license to any other intellectual 68839Sandreas.hansson@arm.com# property including but not limited to intellectual property relating 78839Sandreas.hansson@arm.com# to a hardware implementation of the functionality of the software 88839Sandreas.hansson@arm.com# licensed hereunder. You may use the software subject to the license 98839Sandreas.hansson@arm.com# terms below provided that you ensure that this notice is replicated 108839Sandreas.hansson@arm.com# unmodified and in its entirety in all distributions of the software, 118839Sandreas.hansson@arm.com# modified or unmodified, in source code or in binary form. 128839Sandreas.hansson@arm.com# 133101Sstever@eecs.umich.edu# Copyright (c) 2004-2006 The Regents of The University of Michigan 148579Ssteve.reinhardt@amd.com# Copyright (c) 2010-2011 Advanced Micro Devices, Inc. 153101Sstever@eecs.umich.edu# All rights reserved. 163101Sstever@eecs.umich.edu# 173101Sstever@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 183101Sstever@eecs.umich.edu# modification, are permitted provided that the following conditions are 193101Sstever@eecs.umich.edu# met: redistributions of source code must retain the above copyright 203101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 213101Sstever@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 223101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 233101Sstever@eecs.umich.edu# documentation and/or other materials provided with the distribution; 243101Sstever@eecs.umich.edu# neither the name of the copyright holders nor the names of its 253101Sstever@eecs.umich.edu# contributors may be used to endorse or promote products derived from 263101Sstever@eecs.umich.edu# this software without specific prior written permission. 273101Sstever@eecs.umich.edu# 283101Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 293101Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 303101Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 313101Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 323101Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 333101Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 343101Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 353101Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 363101Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 373101Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 383101Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 393101Sstever@eecs.umich.edu# 403101Sstever@eecs.umich.edu# Authors: Steve Reinhardt 413101Sstever@eecs.umich.edu# Nathan Binkert 427778Sgblack@eecs.umich.edu# Gabe Black 438839Sandreas.hansson@arm.com# Andreas Hansson 443101Sstever@eecs.umich.edu 453101Sstever@eecs.umich.edu##################################################################### 463101Sstever@eecs.umich.edu# 473101Sstever@eecs.umich.edu# Parameter description classes 483101Sstever@eecs.umich.edu# 493101Sstever@eecs.umich.edu# The _params dictionary in each class maps parameter names to either 503101Sstever@eecs.umich.edu# a Param or a VectorParam object. These objects contain the 513101Sstever@eecs.umich.edu# parameter description string, the parameter type, and the default 523101Sstever@eecs.umich.edu# value (if any). The convert() method on these objects is used to 533101Sstever@eecs.umich.edu# force whatever value is assigned to the parameter to the appropriate 543101Sstever@eecs.umich.edu# type. 553101Sstever@eecs.umich.edu# 563101Sstever@eecs.umich.edu# Note that the default values are loaded into the class's attribute 573101Sstever@eecs.umich.edu# space when the parameter dictionary is initialized (in 583101Sstever@eecs.umich.edu# MetaSimObject._new_param()); after that point they aren't used. 593101Sstever@eecs.umich.edu# 603101Sstever@eecs.umich.edu##################################################################### 613101Sstever@eecs.umich.edu 623885Sbinkertn@umich.eduimport copy 633885Sbinkertn@umich.eduimport datetime 644762Snate@binkert.orgimport re 653885Sbinkertn@umich.eduimport sys 663885Sbinkertn@umich.eduimport time 677528Ssteve.reinhardt@amd.comimport math 683885Sbinkertn@umich.edu 694380Sbinkertn@umich.eduimport proxy 704167Sbinkertn@umich.eduimport ticks 713102Sstever@eecs.umich.edufrom util import * 723101Sstever@eecs.umich.edu 734762Snate@binkert.orgdef isSimObject(*args, **kwargs): 744762Snate@binkert.org return SimObject.isSimObject(*args, **kwargs) 754762Snate@binkert.org 764762Snate@binkert.orgdef isSimObjectSequence(*args, **kwargs): 774762Snate@binkert.org return SimObject.isSimObjectSequence(*args, **kwargs) 784762Snate@binkert.org 794762Snate@binkert.orgdef isSimObjectClass(*args, **kwargs): 804762Snate@binkert.org return SimObject.isSimObjectClass(*args, **kwargs) 814762Snate@binkert.org 825033Smilesck@eecs.umich.eduallParams = {} 835033Smilesck@eecs.umich.edu 845033Smilesck@eecs.umich.educlass MetaParamValue(type): 855033Smilesck@eecs.umich.edu def __new__(mcls, name, bases, dct): 865033Smilesck@eecs.umich.edu cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) 875033Smilesck@eecs.umich.edu assert name not in allParams 885033Smilesck@eecs.umich.edu allParams[name] = cls 895033Smilesck@eecs.umich.edu return cls 905033Smilesck@eecs.umich.edu 915033Smilesck@eecs.umich.edu 923101Sstever@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject 933101Sstever@eecs.umich.edu# parameters. 943101Sstever@eecs.umich.educlass ParamValue(object): 955033Smilesck@eecs.umich.edu __metaclass__ = MetaParamValue 963101Sstever@eecs.umich.edu 978596Ssteve.reinhardt@amd.com 988596Ssteve.reinhardt@amd.com # Generate the code needed as a prerequisite for declaring a C++ 998596Ssteve.reinhardt@amd.com # object of this type. Typically generates one or more #include 1008596Ssteve.reinhardt@amd.com # statements. Used when declaring parameters of this type. 1017673Snate@binkert.org @classmethod 1027673Snate@binkert.org def cxx_predecls(cls, code): 1037673Snate@binkert.org pass 1047673Snate@binkert.org 1058596Ssteve.reinhardt@amd.com # Generate the code needed as a prerequisite for including a 1068596Ssteve.reinhardt@amd.com # reference to a C++ object of this type in a SWIG .i file. 1078596Ssteve.reinhardt@amd.com # Typically generates one or more %import or %include statements. 1087673Snate@binkert.org @classmethod 1097673Snate@binkert.org def swig_predecls(cls, code): 1107673Snate@binkert.org pass 1113101Sstever@eecs.umich.edu 1123101Sstever@eecs.umich.edu # default for printing to .ini file is regular string conversion. 1133101Sstever@eecs.umich.edu # will be overridden in some cases 1143101Sstever@eecs.umich.edu def ini_str(self): 1153101Sstever@eecs.umich.edu return str(self) 1163101Sstever@eecs.umich.edu 1173101Sstever@eecs.umich.edu # allows us to blithely call unproxy() on things without checking 1183101Sstever@eecs.umich.edu # if they're really proxies or not 1193101Sstever@eecs.umich.edu def unproxy(self, base): 1203101Sstever@eecs.umich.edu return self 1213101Sstever@eecs.umich.edu 1223101Sstever@eecs.umich.edu# Regular parameter description. 1233101Sstever@eecs.umich.educlass ParamDesc(object): 1243101Sstever@eecs.umich.edu def __init__(self, ptype_str, ptype, *args, **kwargs): 1253101Sstever@eecs.umich.edu self.ptype_str = ptype_str 1263101Sstever@eecs.umich.edu # remember ptype only if it is provided 1273101Sstever@eecs.umich.edu if ptype != None: 1283101Sstever@eecs.umich.edu self.ptype = ptype 1293101Sstever@eecs.umich.edu 1303101Sstever@eecs.umich.edu if args: 1313101Sstever@eecs.umich.edu if len(args) == 1: 1323101Sstever@eecs.umich.edu self.desc = args[0] 1333101Sstever@eecs.umich.edu elif len(args) == 2: 1343101Sstever@eecs.umich.edu self.default = args[0] 1353101Sstever@eecs.umich.edu self.desc = args[1] 1363101Sstever@eecs.umich.edu else: 1373101Sstever@eecs.umich.edu raise TypeError, 'too many arguments' 1383101Sstever@eecs.umich.edu 1393101Sstever@eecs.umich.edu if kwargs.has_key('desc'): 1403101Sstever@eecs.umich.edu assert(not hasattr(self, 'desc')) 1413101Sstever@eecs.umich.edu self.desc = kwargs['desc'] 1423101Sstever@eecs.umich.edu del kwargs['desc'] 1433101Sstever@eecs.umich.edu 1443101Sstever@eecs.umich.edu if kwargs.has_key('default'): 1453101Sstever@eecs.umich.edu assert(not hasattr(self, 'default')) 1463101Sstever@eecs.umich.edu self.default = kwargs['default'] 1473101Sstever@eecs.umich.edu del kwargs['default'] 1483101Sstever@eecs.umich.edu 1493101Sstever@eecs.umich.edu if kwargs: 1503101Sstever@eecs.umich.edu raise TypeError, 'extra unknown kwargs %s' % kwargs 1513101Sstever@eecs.umich.edu 1523101Sstever@eecs.umich.edu if not hasattr(self, 'desc'): 1533101Sstever@eecs.umich.edu raise TypeError, 'desc attribute missing' 1543101Sstever@eecs.umich.edu 1553101Sstever@eecs.umich.edu def __getattr__(self, attr): 1563101Sstever@eecs.umich.edu if attr == 'ptype': 1575033Smilesck@eecs.umich.edu ptype = SimObject.allClasses[self.ptype_str] 1586656Snate@binkert.org assert isSimObjectClass(ptype) 1595033Smilesck@eecs.umich.edu self.ptype = ptype 1605033Smilesck@eecs.umich.edu return ptype 1615033Smilesck@eecs.umich.edu 1623101Sstever@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 1633101Sstever@eecs.umich.edu (type(self).__name__, attr) 1643101Sstever@eecs.umich.edu 1653101Sstever@eecs.umich.edu def convert(self, value): 1663101Sstever@eecs.umich.edu if isinstance(value, proxy.BaseProxy): 1673101Sstever@eecs.umich.edu value.set_param_desc(self) 1683101Sstever@eecs.umich.edu return value 1693101Sstever@eecs.umich.edu if not hasattr(self, 'ptype') and isNullPointer(value): 1703101Sstever@eecs.umich.edu # deferred evaluation of SimObject; continue to defer if 1713101Sstever@eecs.umich.edu # we're just assigning a null pointer 1723101Sstever@eecs.umich.edu return value 1733101Sstever@eecs.umich.edu if isinstance(value, self.ptype): 1743101Sstever@eecs.umich.edu return value 1753102Sstever@eecs.umich.edu if isNullPointer(value) and isSimObjectClass(self.ptype): 1763101Sstever@eecs.umich.edu return value 1773101Sstever@eecs.umich.edu return self.ptype(value) 1783101Sstever@eecs.umich.edu 1797673Snate@binkert.org def cxx_predecls(self, code): 1808607Sgblack@eecs.umich.edu code('#include <cstddef>') 1817673Snate@binkert.org self.ptype.cxx_predecls(code) 1823101Sstever@eecs.umich.edu 1837673Snate@binkert.org def swig_predecls(self, code): 1847673Snate@binkert.org self.ptype.swig_predecls(code) 1853101Sstever@eecs.umich.edu 1867673Snate@binkert.org def cxx_decl(self, code): 1877673Snate@binkert.org code('${{self.ptype.cxx_type}} ${{self.name}};') 1883101Sstever@eecs.umich.edu 1893101Sstever@eecs.umich.edu# Vector-valued parameter description. Just like ParamDesc, except 1903101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a 1913101Sstever@eecs.umich.edu# single value. 1923101Sstever@eecs.umich.edu 1933101Sstever@eecs.umich.educlass VectorParamValue(list): 1945033Smilesck@eecs.umich.edu __metaclass__ = MetaParamValue 1955475Snate@binkert.org def __setattr__(self, attr, value): 1965475Snate@binkert.org raise AttributeError, \ 1975475Snate@binkert.org "Not allowed to set %s on '%s'" % (attr, type(self).__name__) 1985475Snate@binkert.org 1993101Sstever@eecs.umich.edu def ini_str(self): 2003101Sstever@eecs.umich.edu return ' '.join([v.ini_str() for v in self]) 2013101Sstever@eecs.umich.edu 2024762Snate@binkert.org def getValue(self): 2034762Snate@binkert.org return [ v.getValue() for v in self ] 2044762Snate@binkert.org 2053101Sstever@eecs.umich.edu def unproxy(self, base): 2068460SAli.Saidi@ARM.com if len(self) == 1 and isinstance(self[0], proxy.AllProxy): 2078459SAli.Saidi@ARM.com return self[0].unproxy(base) 2088459SAli.Saidi@ARM.com else: 2098459SAli.Saidi@ARM.com return [v.unproxy(base) for v in self] 2103101Sstever@eecs.umich.edu 2117528Ssteve.reinhardt@amd.comclass SimObjectVector(VectorParamValue): 2127528Ssteve.reinhardt@amd.com # support clone operation 2137528Ssteve.reinhardt@amd.com def __call__(self, **kwargs): 2147528Ssteve.reinhardt@amd.com return SimObjectVector([v(**kwargs) for v in self]) 2157528Ssteve.reinhardt@amd.com 2167528Ssteve.reinhardt@amd.com def clear_parent(self, old_parent): 2173101Sstever@eecs.umich.edu for v in self: 2187528Ssteve.reinhardt@amd.com v.clear_parent(old_parent) 2197528Ssteve.reinhardt@amd.com 2207528Ssteve.reinhardt@amd.com def set_parent(self, parent, name): 2217528Ssteve.reinhardt@amd.com if len(self) == 1: 2227528Ssteve.reinhardt@amd.com self[0].set_parent(parent, name) 2237528Ssteve.reinhardt@amd.com else: 2247528Ssteve.reinhardt@amd.com width = int(math.ceil(math.log(len(self))/math.log(10))) 2257528Ssteve.reinhardt@amd.com for i,v in enumerate(self): 2267528Ssteve.reinhardt@amd.com v.set_parent(parent, "%s%0*d" % (name, width, i)) 2277528Ssteve.reinhardt@amd.com 2288321Ssteve.reinhardt@amd.com def has_parent(self): 2298321Ssteve.reinhardt@amd.com return reduce(lambda x,y: x and y, [v.has_parent() for v in self]) 2307528Ssteve.reinhardt@amd.com 2317528Ssteve.reinhardt@amd.com # return 'cpu0 cpu1' etc. for print_ini() 2327528Ssteve.reinhardt@amd.com def get_name(self): 2337528Ssteve.reinhardt@amd.com return ' '.join([v._name for v in self]) 2347528Ssteve.reinhardt@amd.com 2357528Ssteve.reinhardt@amd.com # By iterating through the constituent members of the vector here 2367528Ssteve.reinhardt@amd.com # we can nicely handle iterating over all a SimObject's children 2377528Ssteve.reinhardt@amd.com # without having to provide lots of special functions on 2387528Ssteve.reinhardt@amd.com # SimObjectVector directly. 2397528Ssteve.reinhardt@amd.com def descendants(self): 2407528Ssteve.reinhardt@amd.com for v in self: 2417528Ssteve.reinhardt@amd.com for obj in v.descendants(): 2427528Ssteve.reinhardt@amd.com yield obj 2433101Sstever@eecs.umich.edu 2448664SAli.Saidi@ARM.com def get_config_as_dict(self): 2458664SAli.Saidi@ARM.com a = [] 2468664SAli.Saidi@ARM.com for v in self: 2478664SAli.Saidi@ARM.com a.append(v.get_config_as_dict()) 2488664SAli.Saidi@ARM.com return a 2498664SAli.Saidi@ARM.com 2509953Sgeoffrey.blake@arm.com # If we are replacing an item in the vector, make sure to set the 2519953Sgeoffrey.blake@arm.com # parent reference of the new SimObject to be the same as the parent 2529953Sgeoffrey.blake@arm.com # of the SimObject being replaced. Useful to have if we created 2539953Sgeoffrey.blake@arm.com # a SimObjectVector of temporary objects that will be modified later in 2549953Sgeoffrey.blake@arm.com # configuration scripts. 2559953Sgeoffrey.blake@arm.com def __setitem__(self, key, value): 2569953Sgeoffrey.blake@arm.com val = self[key] 2579953Sgeoffrey.blake@arm.com if value.has_parent(): 2589953Sgeoffrey.blake@arm.com warn("SimObject %s already has a parent" % value.get_name() +\ 2599953Sgeoffrey.blake@arm.com " that is being overwritten by a SimObjectVector") 2609953Sgeoffrey.blake@arm.com value.set_parent(val.get_parent(), val._name) 2619953Sgeoffrey.blake@arm.com super(SimObjectVector, self).__setitem__(key, value) 2629953Sgeoffrey.blake@arm.com 2633101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc): 2643101Sstever@eecs.umich.edu # Convert assigned value to appropriate type. If the RHS is not a 2653101Sstever@eecs.umich.edu # list or tuple, it generates a single-element list. 2663101Sstever@eecs.umich.edu def convert(self, value): 2673101Sstever@eecs.umich.edu if isinstance(value, (list, tuple)): 2683101Sstever@eecs.umich.edu # list: coerce each element into new list 2693101Sstever@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) for v in value ] 2703101Sstever@eecs.umich.edu else: 2714762Snate@binkert.org # singleton: coerce to a single-element list 2724762Snate@binkert.org tmp_list = [ ParamDesc.convert(self, value) ] 2734762Snate@binkert.org 2744762Snate@binkert.org if isSimObjectSequence(tmp_list): 2757528Ssteve.reinhardt@amd.com return SimObjectVector(tmp_list) 2764762Snate@binkert.org else: 2774762Snate@binkert.org return VectorParamValue(tmp_list) 2784762Snate@binkert.org 2798596Ssteve.reinhardt@amd.com def swig_module_name(self): 2808596Ssteve.reinhardt@amd.com return "%s_vector" % self.ptype_str 2818596Ssteve.reinhardt@amd.com 2827673Snate@binkert.org def swig_predecls(self, code): 2838596Ssteve.reinhardt@amd.com code('%import "${{self.swig_module_name()}}.i"') 2844762Snate@binkert.org 2857673Snate@binkert.org def swig_decl(self, code): 2868596Ssteve.reinhardt@amd.com code('%module(package="m5.internal") ${{self.swig_module_name()}}') 2877675Snate@binkert.org code('%{') 2887675Snate@binkert.org self.ptype.cxx_predecls(code) 2897675Snate@binkert.org code('%}') 2907675Snate@binkert.org code() 2918656Sandreas.hansson@arm.com # Make sure the SWIGPY_SLICE_ARG is defined through this inclusion 2928656Sandreas.hansson@arm.com code('%include "std_container.i"') 2938656Sandreas.hansson@arm.com code() 2947675Snate@binkert.org self.ptype.swig_predecls(code) 2957675Snate@binkert.org code() 2967673Snate@binkert.org code('%include "std_vector.i"') 2977675Snate@binkert.org code() 2987675Snate@binkert.org 2997675Snate@binkert.org ptype = self.ptype_str 3007675Snate@binkert.org cxx_type = self.ptype.cxx_type 3017675Snate@binkert.org 3027675Snate@binkert.org code('%template(vector_$ptype) std::vector< $cxx_type >;') 3037675Snate@binkert.org 3047673Snate@binkert.org def cxx_predecls(self, code): 3057673Snate@binkert.org code('#include <vector>') 3067673Snate@binkert.org self.ptype.cxx_predecls(code) 3073101Sstever@eecs.umich.edu 3087673Snate@binkert.org def cxx_decl(self, code): 3097673Snate@binkert.org code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};') 3103101Sstever@eecs.umich.edu 3113101Sstever@eecs.umich.educlass ParamFactory(object): 3123101Sstever@eecs.umich.edu def __init__(self, param_desc_class, ptype_str = None): 3133101Sstever@eecs.umich.edu self.param_desc_class = param_desc_class 3143101Sstever@eecs.umich.edu self.ptype_str = ptype_str 3153101Sstever@eecs.umich.edu 3163101Sstever@eecs.umich.edu def __getattr__(self, attr): 3173101Sstever@eecs.umich.edu if self.ptype_str: 3183101Sstever@eecs.umich.edu attr = self.ptype_str + '.' + attr 3193101Sstever@eecs.umich.edu return ParamFactory(self.param_desc_class, attr) 3203101Sstever@eecs.umich.edu 3213101Sstever@eecs.umich.edu # E.g., Param.Int(5, "number of widgets") 3223101Sstever@eecs.umich.edu def __call__(self, *args, **kwargs): 3233101Sstever@eecs.umich.edu ptype = None 3243101Sstever@eecs.umich.edu try: 3255033Smilesck@eecs.umich.edu ptype = allParams[self.ptype_str] 3265033Smilesck@eecs.umich.edu except KeyError: 3273101Sstever@eecs.umich.edu # if name isn't defined yet, assume it's a SimObject, and 3283101Sstever@eecs.umich.edu # try to resolve it later 3293101Sstever@eecs.umich.edu pass 3303101Sstever@eecs.umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 3313101Sstever@eecs.umich.edu 3323101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc) 3333101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc) 3343101Sstever@eecs.umich.edu 3353101Sstever@eecs.umich.edu##################################################################### 3363101Sstever@eecs.umich.edu# 3373101Sstever@eecs.umich.edu# Parameter Types 3383101Sstever@eecs.umich.edu# 3393101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types 3403101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more 3413101Sstever@eecs.umich.edu# flexible to define our own set of types. This gives us more control 3423101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the 3433101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via 3443101Sstever@eecs.umich.edu# the __str__() conversion method). 3453101Sstever@eecs.umich.edu# 3463101Sstever@eecs.umich.edu##################################################################### 3473101Sstever@eecs.umich.edu 3483101Sstever@eecs.umich.edu# String-valued parameter. Just mixin the ParamValue class with the 3493101Sstever@eecs.umich.edu# built-in str class. 3503101Sstever@eecs.umich.educlass String(ParamValue,str): 3513101Sstever@eecs.umich.edu cxx_type = 'std::string' 3527673Snate@binkert.org 3537673Snate@binkert.org @classmethod 3547673Snate@binkert.org def cxx_predecls(self, code): 3557673Snate@binkert.org code('#include <string>') 3567673Snate@binkert.org 3577673Snate@binkert.org @classmethod 3587673Snate@binkert.org def swig_predecls(cls, code): 3597673Snate@binkert.org code('%include "std_string.i"') 3604762Snate@binkert.org 3614762Snate@binkert.org def getValue(self): 3624762Snate@binkert.org return self 3633101Sstever@eecs.umich.edu 3643101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math 3653101Sstever@eecs.umich.edu# operations in a type-safe way. e.g., a Latency times an int returns 3663101Sstever@eecs.umich.edu# a new Latency object. 3673101Sstever@eecs.umich.educlass NumericParamValue(ParamValue): 3683101Sstever@eecs.umich.edu def __str__(self): 3693101Sstever@eecs.umich.edu return str(self.value) 3703101Sstever@eecs.umich.edu 3713101Sstever@eecs.umich.edu def __float__(self): 3723101Sstever@eecs.umich.edu return float(self.value) 3733101Sstever@eecs.umich.edu 3743714Sstever@eecs.umich.edu def __long__(self): 3753714Sstever@eecs.umich.edu return long(self.value) 3763714Sstever@eecs.umich.edu 3773714Sstever@eecs.umich.edu def __int__(self): 3783714Sstever@eecs.umich.edu return int(self.value) 3793714Sstever@eecs.umich.edu 3803101Sstever@eecs.umich.edu # hook for bounds checking 3813101Sstever@eecs.umich.edu def _check(self): 3823101Sstever@eecs.umich.edu return 3833101Sstever@eecs.umich.edu 3843101Sstever@eecs.umich.edu def __mul__(self, other): 3853101Sstever@eecs.umich.edu newobj = self.__class__(self) 3863101Sstever@eecs.umich.edu newobj.value *= other 3873101Sstever@eecs.umich.edu newobj._check() 3883101Sstever@eecs.umich.edu return newobj 3893101Sstever@eecs.umich.edu 3903101Sstever@eecs.umich.edu __rmul__ = __mul__ 3913101Sstever@eecs.umich.edu 3923101Sstever@eecs.umich.edu def __div__(self, other): 3933101Sstever@eecs.umich.edu newobj = self.__class__(self) 3943101Sstever@eecs.umich.edu newobj.value /= other 3953101Sstever@eecs.umich.edu newobj._check() 3963101Sstever@eecs.umich.edu return newobj 3973101Sstever@eecs.umich.edu 3983101Sstever@eecs.umich.edu def __sub__(self, other): 3993101Sstever@eecs.umich.edu newobj = self.__class__(self) 4003101Sstever@eecs.umich.edu newobj.value -= other 4013101Sstever@eecs.umich.edu newobj._check() 4023101Sstever@eecs.umich.edu return newobj 4033101Sstever@eecs.umich.edu 4043101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters. See CheckedInt. 4055033Smilesck@eecs.umich.educlass CheckedIntType(MetaParamValue): 4063101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 4073101Sstever@eecs.umich.edu super(CheckedIntType, cls).__init__(name, bases, dict) 4083101Sstever@eecs.umich.edu 4093101Sstever@eecs.umich.edu # CheckedInt is an abstract base class, so we actually don't 4103101Sstever@eecs.umich.edu # want to do any processing on it... the rest of this code is 4113101Sstever@eecs.umich.edu # just for classes that derive from CheckedInt. 4123101Sstever@eecs.umich.edu if name == 'CheckedInt': 4133101Sstever@eecs.umich.edu return 4143101Sstever@eecs.umich.edu 4153101Sstever@eecs.umich.edu if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 4163101Sstever@eecs.umich.edu if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 4173101Sstever@eecs.umich.edu panic("CheckedInt subclass %s must define either\n" \ 4185822Ssaidi@eecs.umich.edu " 'min' and 'max' or 'size' and 'unsigned'\n", 4195822Ssaidi@eecs.umich.edu name); 4203101Sstever@eecs.umich.edu if cls.unsigned: 4213101Sstever@eecs.umich.edu cls.min = 0 4223101Sstever@eecs.umich.edu cls.max = 2 ** cls.size - 1 4233101Sstever@eecs.umich.edu else: 4243101Sstever@eecs.umich.edu cls.min = -(2 ** (cls.size - 1)) 4253101Sstever@eecs.umich.edu cls.max = (2 ** (cls.size - 1)) - 1 4263101Sstever@eecs.umich.edu 4273101Sstever@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters. This 4283101Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific 4293101Sstever@eecs.umich.edu# bounds. Initialization of the min and max bounds is done in the 4303101Sstever@eecs.umich.edu# metaclass CheckedIntType.__init__. 4313101Sstever@eecs.umich.educlass CheckedInt(NumericParamValue): 4323101Sstever@eecs.umich.edu __metaclass__ = CheckedIntType 4333101Sstever@eecs.umich.edu 4343101Sstever@eecs.umich.edu def _check(self): 4353101Sstever@eecs.umich.edu if not self.min <= self.value <= self.max: 4363101Sstever@eecs.umich.edu raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 4373101Sstever@eecs.umich.edu (self.min, self.value, self.max) 4383101Sstever@eecs.umich.edu 4393101Sstever@eecs.umich.edu def __init__(self, value): 4403101Sstever@eecs.umich.edu if isinstance(value, str): 4413102Sstever@eecs.umich.edu self.value = convert.toInteger(value) 4423714Sstever@eecs.umich.edu elif isinstance(value, (int, long, float, NumericParamValue)): 4433101Sstever@eecs.umich.edu self.value = long(value) 4443714Sstever@eecs.umich.edu else: 4453714Sstever@eecs.umich.edu raise TypeError, "Can't convert object of type %s to CheckedInt" \ 4463714Sstever@eecs.umich.edu % type(value).__name__ 4473101Sstever@eecs.umich.edu self._check() 4483101Sstever@eecs.umich.edu 4497673Snate@binkert.org @classmethod 4507673Snate@binkert.org def cxx_predecls(cls, code): 4517673Snate@binkert.org # most derived types require this, so we just do it here once 4527673Snate@binkert.org code('#include "base/types.hh"') 4537673Snate@binkert.org 4547673Snate@binkert.org @classmethod 4557673Snate@binkert.org def swig_predecls(cls, code): 4567673Snate@binkert.org # most derived types require this, so we just do it here once 4577673Snate@binkert.org code('%import "stdint.i"') 4587673Snate@binkert.org code('%import "base/types.hh"') 4597673Snate@binkert.org 4604762Snate@binkert.org def getValue(self): 4614762Snate@binkert.org return long(self.value) 4624762Snate@binkert.org 4633101Sstever@eecs.umich.educlass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 4643101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 4653101Sstever@eecs.umich.edu 4663101Sstever@eecs.umich.educlass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 4673101Sstever@eecs.umich.educlass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 4683101Sstever@eecs.umich.educlass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 4693101Sstever@eecs.umich.educlass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 4703101Sstever@eecs.umich.educlass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 4713101Sstever@eecs.umich.educlass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 4723101Sstever@eecs.umich.educlass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 4733101Sstever@eecs.umich.educlass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 4743101Sstever@eecs.umich.edu 4753101Sstever@eecs.umich.educlass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 4763101Sstever@eecs.umich.educlass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 4773101Sstever@eecs.umich.educlass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 4783101Sstever@eecs.umich.educlass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 4793101Sstever@eecs.umich.edu 4803101Sstever@eecs.umich.educlass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 4813101Sstever@eecs.umich.edu 4829184Sandreas.hansson@arm.comclass Cycles(CheckedInt): 4839184Sandreas.hansson@arm.com cxx_type = 'Cycles' 4849184Sandreas.hansson@arm.com size = 64 4859184Sandreas.hansson@arm.com unsigned = True 4869184Sandreas.hansson@arm.com 4879184Sandreas.hansson@arm.com def getValue(self): 4889184Sandreas.hansson@arm.com from m5.internal.core import Cycles 4899184Sandreas.hansson@arm.com return Cycles(self.value) 4909184Sandreas.hansson@arm.com 4913101Sstever@eecs.umich.educlass Float(ParamValue, float): 4924446Sbinkertn@umich.edu cxx_type = 'double' 4933101Sstever@eecs.umich.edu 4945468Snate@binkert.org def __init__(self, value): 4955468Snate@binkert.org if isinstance(value, (int, long, float, NumericParamValue, Float)): 4965468Snate@binkert.org self.value = float(value) 4975468Snate@binkert.org else: 4985468Snate@binkert.org raise TypeError, "Can't convert object of type %s to Float" \ 4995468Snate@binkert.org % type(value).__name__ 5005468Snate@binkert.org 5014762Snate@binkert.org def getValue(self): 5024762Snate@binkert.org return float(self.value) 5034762Snate@binkert.org 5043101Sstever@eecs.umich.educlass MemorySize(CheckedInt): 5053101Sstever@eecs.umich.edu cxx_type = 'uint64_t' 5063101Sstever@eecs.umich.edu size = 64 5073101Sstever@eecs.umich.edu unsigned = True 5083101Sstever@eecs.umich.edu def __init__(self, value): 5093101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 5103101Sstever@eecs.umich.edu self.value = value.value 5113101Sstever@eecs.umich.edu else: 5123102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 5133101Sstever@eecs.umich.edu self._check() 5143101Sstever@eecs.umich.edu 5153101Sstever@eecs.umich.educlass MemorySize32(CheckedInt): 5164168Sbinkertn@umich.edu cxx_type = 'uint32_t' 5173101Sstever@eecs.umich.edu size = 32 5183101Sstever@eecs.umich.edu unsigned = True 5193101Sstever@eecs.umich.edu def __init__(self, value): 5203101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 5213101Sstever@eecs.umich.edu self.value = value.value 5223101Sstever@eecs.umich.edu else: 5233102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 5243101Sstever@eecs.umich.edu self._check() 5253101Sstever@eecs.umich.edu 5263101Sstever@eecs.umich.educlass Addr(CheckedInt): 5273101Sstever@eecs.umich.edu cxx_type = 'Addr' 5283101Sstever@eecs.umich.edu size = 64 5293101Sstever@eecs.umich.edu unsigned = True 5303101Sstever@eecs.umich.edu def __init__(self, value): 5313101Sstever@eecs.umich.edu if isinstance(value, Addr): 5323101Sstever@eecs.umich.edu self.value = value.value 5333101Sstever@eecs.umich.edu else: 5343101Sstever@eecs.umich.edu try: 5353102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 5363101Sstever@eecs.umich.edu except TypeError: 5373101Sstever@eecs.umich.edu self.value = long(value) 5383101Sstever@eecs.umich.edu self._check() 5393584Ssaidi@eecs.umich.edu def __add__(self, other): 5403584Ssaidi@eecs.umich.edu if isinstance(other, Addr): 5413584Ssaidi@eecs.umich.edu return self.value + other.value 5423584Ssaidi@eecs.umich.edu else: 5433584Ssaidi@eecs.umich.edu return self.value + other 5443101Sstever@eecs.umich.edu 5459232Sandreas.hansson@arm.comclass AddrRange(ParamValue): 5469235Sandreas.hansson@arm.com cxx_type = 'AddrRange' 5473101Sstever@eecs.umich.edu 5483101Sstever@eecs.umich.edu def __init__(self, *args, **kwargs): 5499411Sandreas.hansson@arm.com # Disable interleaving by default 5509411Sandreas.hansson@arm.com self.intlvHighBit = 0 5519411Sandreas.hansson@arm.com self.intlvBits = 0 5529411Sandreas.hansson@arm.com self.intlvMatch = 0 5539411Sandreas.hansson@arm.com 5543101Sstever@eecs.umich.edu def handle_kwargs(self, kwargs): 5559411Sandreas.hansson@arm.com # An address range needs to have an upper limit, specified 5569411Sandreas.hansson@arm.com # either explicitly with an end, or as an offset using the 5579411Sandreas.hansson@arm.com # size keyword. 5583101Sstever@eecs.umich.edu if 'end' in kwargs: 5599232Sandreas.hansson@arm.com self.end = Addr(kwargs.pop('end')) 5603101Sstever@eecs.umich.edu elif 'size' in kwargs: 5619232Sandreas.hansson@arm.com self.end = self.start + Addr(kwargs.pop('size')) - 1 5623101Sstever@eecs.umich.edu else: 5633101Sstever@eecs.umich.edu raise TypeError, "Either end or size must be specified" 5643101Sstever@eecs.umich.edu 5659411Sandreas.hansson@arm.com # Now on to the optional bit 5669411Sandreas.hansson@arm.com if 'intlvHighBit' in kwargs: 5679411Sandreas.hansson@arm.com self.intlvHighBit = int(kwargs.pop('intlvHighBit')) 5689411Sandreas.hansson@arm.com if 'intlvBits' in kwargs: 5699411Sandreas.hansson@arm.com self.intlvBits = int(kwargs.pop('intlvBits')) 5709411Sandreas.hansson@arm.com if 'intlvMatch' in kwargs: 5719411Sandreas.hansson@arm.com self.intlvMatch = int(kwargs.pop('intlvMatch')) 5729411Sandreas.hansson@arm.com 5733101Sstever@eecs.umich.edu if len(args) == 0: 5749232Sandreas.hansson@arm.com self.start = Addr(kwargs.pop('start')) 5753101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 5763101Sstever@eecs.umich.edu 5773101Sstever@eecs.umich.edu elif len(args) == 1: 5783101Sstever@eecs.umich.edu if kwargs: 5799232Sandreas.hansson@arm.com self.start = Addr(args[0]) 5803101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 5815219Ssaidi@eecs.umich.edu elif isinstance(args[0], (list, tuple)): 5829232Sandreas.hansson@arm.com self.start = Addr(args[0][0]) 5839232Sandreas.hansson@arm.com self.end = Addr(args[0][1]) 5843101Sstever@eecs.umich.edu else: 5859232Sandreas.hansson@arm.com self.start = Addr(0) 5869232Sandreas.hansson@arm.com self.end = Addr(args[0]) - 1 5873101Sstever@eecs.umich.edu 5883101Sstever@eecs.umich.edu elif len(args) == 2: 5899232Sandreas.hansson@arm.com self.start = Addr(args[0]) 5909232Sandreas.hansson@arm.com self.end = Addr(args[1]) 5913101Sstever@eecs.umich.edu else: 5923101Sstever@eecs.umich.edu raise TypeError, "Too many arguments specified" 5933101Sstever@eecs.umich.edu 5943101Sstever@eecs.umich.edu if kwargs: 5959232Sandreas.hansson@arm.com raise TypeError, "Too many keywords: %s" % kwargs.keys() 5963101Sstever@eecs.umich.edu 5973101Sstever@eecs.umich.edu def __str__(self): 5989232Sandreas.hansson@arm.com return '%s:%s' % (self.start, self.end) 5999232Sandreas.hansson@arm.com 6009232Sandreas.hansson@arm.com def size(self): 6019411Sandreas.hansson@arm.com # Divide the size by the size of the interleaving slice 6029411Sandreas.hansson@arm.com return (long(self.end) - long(self.start) + 1) >> self.intlvBits 6033101Sstever@eecs.umich.edu 6047673Snate@binkert.org @classmethod 6057673Snate@binkert.org def cxx_predecls(cls, code): 6069232Sandreas.hansson@arm.com Addr.cxx_predecls(code) 6079235Sandreas.hansson@arm.com code('#include "base/addr_range.hh"') 6087675Snate@binkert.org 6097675Snate@binkert.org @classmethod 6107675Snate@binkert.org def swig_predecls(cls, code): 6119232Sandreas.hansson@arm.com Addr.swig_predecls(code) 6127673Snate@binkert.org 6134762Snate@binkert.org def getValue(self): 6149235Sandreas.hansson@arm.com # Go from the Python class to the wrapped C++ class generated 6159235Sandreas.hansson@arm.com # by swig 6167675Snate@binkert.org from m5.internal.range import AddrRange 6174762Snate@binkert.org 6189411Sandreas.hansson@arm.com return AddrRange(long(self.start), long(self.end), 6199411Sandreas.hansson@arm.com int(self.intlvHighBit), int(self.intlvBits), 6209411Sandreas.hansson@arm.com int(self.intlvMatch)) 6213101Sstever@eecs.umich.edu 6223101Sstever@eecs.umich.edu# Boolean parameter type. Python doesn't let you subclass bool, since 6233101Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and 6243101Sstever@eecs.umich.edu# False. Thus this is a little more complicated than String. 6253101Sstever@eecs.umich.educlass Bool(ParamValue): 6263101Sstever@eecs.umich.edu cxx_type = 'bool' 6273101Sstever@eecs.umich.edu def __init__(self, value): 6283101Sstever@eecs.umich.edu try: 6293102Sstever@eecs.umich.edu self.value = convert.toBool(value) 6303101Sstever@eecs.umich.edu except TypeError: 6313101Sstever@eecs.umich.edu self.value = bool(value) 6323101Sstever@eecs.umich.edu 6334762Snate@binkert.org def getValue(self): 6344762Snate@binkert.org return bool(self.value) 6354762Snate@binkert.org 6363101Sstever@eecs.umich.edu def __str__(self): 6373101Sstever@eecs.umich.edu return str(self.value) 6383101Sstever@eecs.umich.edu 6398934SBrad.Beckmann@amd.com # implement truth value testing for Bool parameters so that these params 6408934SBrad.Beckmann@amd.com # evaluate correctly during the python configuration phase 6418934SBrad.Beckmann@amd.com def __nonzero__(self): 6428934SBrad.Beckmann@amd.com return bool(self.value) 6438934SBrad.Beckmann@amd.com 6443101Sstever@eecs.umich.edu def ini_str(self): 6453101Sstever@eecs.umich.edu if self.value: 6463101Sstever@eecs.umich.edu return 'true' 6473101Sstever@eecs.umich.edu return 'false' 6483101Sstever@eecs.umich.edu 6493101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1): 6503101Sstever@eecs.umich.edu bytes = map(lambda x: int(x, 16), addr.split(':')) 6513101Sstever@eecs.umich.edu bytes[5] += val 6523101Sstever@eecs.umich.edu for i in (5, 4, 3, 2, 1): 6533101Sstever@eecs.umich.edu val,rem = divmod(bytes[i], 256) 6543101Sstever@eecs.umich.edu bytes[i] = rem 6553101Sstever@eecs.umich.edu if val == 0: 6563101Sstever@eecs.umich.edu break 6573101Sstever@eecs.umich.edu bytes[i - 1] += val 6583101Sstever@eecs.umich.edu assert(bytes[0] <= 255) 6593101Sstever@eecs.umich.edu return ':'.join(map(lambda x: '%02x' % x, bytes)) 6603101Sstever@eecs.umich.edu 6614380Sbinkertn@umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 6624380Sbinkertn@umich.edudef NextEthernetAddr(): 6634380Sbinkertn@umich.edu global _NextEthernetAddr 6643101Sstever@eecs.umich.edu 6654380Sbinkertn@umich.edu value = _NextEthernetAddr 6664380Sbinkertn@umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 6674380Sbinkertn@umich.edu return value 6683101Sstever@eecs.umich.edu 6693101Sstever@eecs.umich.educlass EthernetAddr(ParamValue): 6703101Sstever@eecs.umich.edu cxx_type = 'Net::EthAddr' 6717673Snate@binkert.org 6727673Snate@binkert.org @classmethod 6737673Snate@binkert.org def cxx_predecls(cls, code): 6747673Snate@binkert.org code('#include "base/inet.hh"') 6757673Snate@binkert.org 6767673Snate@binkert.org @classmethod 6777673Snate@binkert.org def swig_predecls(cls, code): 6787673Snate@binkert.org code('%include "python/swig/inet.i"') 6797673Snate@binkert.org 6803101Sstever@eecs.umich.edu def __init__(self, value): 6813101Sstever@eecs.umich.edu if value == NextEthernetAddr: 6823101Sstever@eecs.umich.edu self.value = value 6833101Sstever@eecs.umich.edu return 6843101Sstever@eecs.umich.edu 6853101Sstever@eecs.umich.edu if not isinstance(value, str): 6863101Sstever@eecs.umich.edu raise TypeError, "expected an ethernet address and didn't get one" 6873101Sstever@eecs.umich.edu 6883101Sstever@eecs.umich.edu bytes = value.split(':') 6893101Sstever@eecs.umich.edu if len(bytes) != 6: 6903101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 6913101Sstever@eecs.umich.edu 6923101Sstever@eecs.umich.edu for byte in bytes: 6939941SGeoffrey.Blake@arm.com if not 0 <= int(byte, base=16) <= 0xff: 6943101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 6953101Sstever@eecs.umich.edu 6963101Sstever@eecs.umich.edu self.value = value 6973101Sstever@eecs.umich.edu 6983101Sstever@eecs.umich.edu def unproxy(self, base): 6993101Sstever@eecs.umich.edu if self.value == NextEthernetAddr: 7004380Sbinkertn@umich.edu return EthernetAddr(self.value()) 7013101Sstever@eecs.umich.edu return self 7023101Sstever@eecs.umich.edu 7034762Snate@binkert.org def getValue(self): 7047677Snate@binkert.org from m5.internal.params import EthAddr 7054762Snate@binkert.org return EthAddr(self.value) 7064762Snate@binkert.org 7074380Sbinkertn@umich.edu def ini_str(self): 7084380Sbinkertn@umich.edu return self.value 7093101Sstever@eecs.umich.edu 7107777Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of 7117777Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP. 7127777Sgblack@eecs.umich.educlass IpAddress(ParamValue): 7137777Sgblack@eecs.umich.edu cxx_type = 'Net::IpAddress' 7147777Sgblack@eecs.umich.edu 7157777Sgblack@eecs.umich.edu @classmethod 7167777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 7177777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 7187777Sgblack@eecs.umich.edu 7197777Sgblack@eecs.umich.edu @classmethod 7207777Sgblack@eecs.umich.edu def swig_predecls(cls, code): 7217777Sgblack@eecs.umich.edu code('%include "python/swig/inet.i"') 7227777Sgblack@eecs.umich.edu 7237777Sgblack@eecs.umich.edu def __init__(self, value): 7247777Sgblack@eecs.umich.edu if isinstance(value, IpAddress): 7257777Sgblack@eecs.umich.edu self.ip = value.ip 7267777Sgblack@eecs.umich.edu else: 7277777Sgblack@eecs.umich.edu try: 7287777Sgblack@eecs.umich.edu self.ip = convert.toIpAddress(value) 7297777Sgblack@eecs.umich.edu except TypeError: 7307777Sgblack@eecs.umich.edu self.ip = long(value) 7317777Sgblack@eecs.umich.edu self.verifyIp() 7327777Sgblack@eecs.umich.edu 7338579Ssteve.reinhardt@amd.com def __str__(self): 7348579Ssteve.reinhardt@amd.com tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)] 7358579Ssteve.reinhardt@amd.com return '%d.%d.%d.%d' % tuple(tup) 7368579Ssteve.reinhardt@amd.com 7378579Ssteve.reinhardt@amd.com def __eq__(self, other): 7388579Ssteve.reinhardt@amd.com if isinstance(other, IpAddress): 7398579Ssteve.reinhardt@amd.com return self.ip == other.ip 7408579Ssteve.reinhardt@amd.com elif isinstance(other, str): 7418579Ssteve.reinhardt@amd.com try: 7428579Ssteve.reinhardt@amd.com return self.ip == convert.toIpAddress(other) 7438579Ssteve.reinhardt@amd.com except: 7448579Ssteve.reinhardt@amd.com return False 7458579Ssteve.reinhardt@amd.com else: 7468579Ssteve.reinhardt@amd.com return self.ip == other 7478579Ssteve.reinhardt@amd.com 7488579Ssteve.reinhardt@amd.com def __ne__(self, other): 7498579Ssteve.reinhardt@amd.com return not (self == other) 7508579Ssteve.reinhardt@amd.com 7517777Sgblack@eecs.umich.edu def verifyIp(self): 7527777Sgblack@eecs.umich.edu if self.ip < 0 or self.ip >= (1 << 32): 7537798Sgblack@eecs.umich.edu raise TypeError, "invalid ip address %#08x" % self.ip 7547777Sgblack@eecs.umich.edu 7557777Sgblack@eecs.umich.edu def getValue(self): 7567777Sgblack@eecs.umich.edu from m5.internal.params import IpAddress 7577777Sgblack@eecs.umich.edu return IpAddress(self.ip) 7587777Sgblack@eecs.umich.edu 7597777Sgblack@eecs.umich.edu# When initializing an IpNetmask, pass in an existing IpNetmask, a string of 7607777Sgblack@eecs.umich.edu# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as 7617777Sgblack@eecs.umich.edu# positional or keyword arguments. 7627777Sgblack@eecs.umich.educlass IpNetmask(IpAddress): 7637777Sgblack@eecs.umich.edu cxx_type = 'Net::IpNetmask' 7647777Sgblack@eecs.umich.edu 7657777Sgblack@eecs.umich.edu @classmethod 7667777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 7677777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 7687777Sgblack@eecs.umich.edu 7697777Sgblack@eecs.umich.edu @classmethod 7707777Sgblack@eecs.umich.edu def swig_predecls(cls, code): 7717777Sgblack@eecs.umich.edu code('%include "python/swig/inet.i"') 7727777Sgblack@eecs.umich.edu 7737777Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 7747777Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 7757777Sgblack@eecs.umich.edu if key in kwargs: 7767777Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 7777777Sgblack@eecs.umich.edu elif elseVal: 7787777Sgblack@eecs.umich.edu setattr(self, key, elseVal) 7797777Sgblack@eecs.umich.edu else: 7807777Sgblack@eecs.umich.edu raise TypeError, "No value set for %s" % key 7817777Sgblack@eecs.umich.edu 7827777Sgblack@eecs.umich.edu if len(args) == 0: 7837777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip') 7847777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask') 7857777Sgblack@eecs.umich.edu 7867777Sgblack@eecs.umich.edu elif len(args) == 1: 7877777Sgblack@eecs.umich.edu if kwargs: 7887777Sgblack@eecs.umich.edu if not 'ip' in kwargs and not 'netmask' in kwargs: 7897777Sgblack@eecs.umich.edu raise TypeError, "Invalid arguments" 7907777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 7917777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask', args[0]) 7927777Sgblack@eecs.umich.edu elif isinstance(args[0], IpNetmask): 7937777Sgblack@eecs.umich.edu self.ip = args[0].ip 7947777Sgblack@eecs.umich.edu self.netmask = args[0].netmask 7957777Sgblack@eecs.umich.edu else: 7967777Sgblack@eecs.umich.edu (self.ip, self.netmask) = convert.toIpNetmask(args[0]) 7977777Sgblack@eecs.umich.edu 7987777Sgblack@eecs.umich.edu elif len(args) == 2: 7997777Sgblack@eecs.umich.edu self.ip = args[0] 8007777Sgblack@eecs.umich.edu self.netmask = args[1] 8017777Sgblack@eecs.umich.edu else: 8027777Sgblack@eecs.umich.edu raise TypeError, "Too many arguments specified" 8037777Sgblack@eecs.umich.edu 8047777Sgblack@eecs.umich.edu if kwargs: 8057777Sgblack@eecs.umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 8067777Sgblack@eecs.umich.edu 8077777Sgblack@eecs.umich.edu self.verify() 8087777Sgblack@eecs.umich.edu 8098579Ssteve.reinhardt@amd.com def __str__(self): 8108579Ssteve.reinhardt@amd.com return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask) 8118579Ssteve.reinhardt@amd.com 8128579Ssteve.reinhardt@amd.com def __eq__(self, other): 8138579Ssteve.reinhardt@amd.com if isinstance(other, IpNetmask): 8148579Ssteve.reinhardt@amd.com return self.ip == other.ip and self.netmask == other.netmask 8158579Ssteve.reinhardt@amd.com elif isinstance(other, str): 8168579Ssteve.reinhardt@amd.com try: 8178579Ssteve.reinhardt@amd.com return (self.ip, self.netmask) == convert.toIpNetmask(other) 8188579Ssteve.reinhardt@amd.com except: 8198579Ssteve.reinhardt@amd.com return False 8208579Ssteve.reinhardt@amd.com else: 8218579Ssteve.reinhardt@amd.com return False 8228579Ssteve.reinhardt@amd.com 8237777Sgblack@eecs.umich.edu def verify(self): 8247777Sgblack@eecs.umich.edu self.verifyIp() 8257777Sgblack@eecs.umich.edu if self.netmask < 0 or self.netmask > 32: 8267777Sgblack@eecs.umich.edu raise TypeError, "invalid netmask %d" % netmask 8277777Sgblack@eecs.umich.edu 8287777Sgblack@eecs.umich.edu def getValue(self): 8297777Sgblack@eecs.umich.edu from m5.internal.params import IpNetmask 8307777Sgblack@eecs.umich.edu return IpNetmask(self.ip, self.netmask) 8317777Sgblack@eecs.umich.edu 8327777Sgblack@eecs.umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of 8337777Sgblack@eecs.umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments. 8347777Sgblack@eecs.umich.educlass IpWithPort(IpAddress): 8357777Sgblack@eecs.umich.edu cxx_type = 'Net::IpWithPort' 8367777Sgblack@eecs.umich.edu 8377777Sgblack@eecs.umich.edu @classmethod 8387777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 8397777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 8407777Sgblack@eecs.umich.edu 8417777Sgblack@eecs.umich.edu @classmethod 8427777Sgblack@eecs.umich.edu def swig_predecls(cls, code): 8437777Sgblack@eecs.umich.edu code('%include "python/swig/inet.i"') 8447777Sgblack@eecs.umich.edu 8457777Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 8467777Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 8477777Sgblack@eecs.umich.edu if key in kwargs: 8487777Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 8497777Sgblack@eecs.umich.edu elif elseVal: 8507777Sgblack@eecs.umich.edu setattr(self, key, elseVal) 8517777Sgblack@eecs.umich.edu else: 8527777Sgblack@eecs.umich.edu raise TypeError, "No value set for %s" % key 8537777Sgblack@eecs.umich.edu 8547777Sgblack@eecs.umich.edu if len(args) == 0: 8557777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip') 8567777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'port') 8577777Sgblack@eecs.umich.edu 8587777Sgblack@eecs.umich.edu elif len(args) == 1: 8597777Sgblack@eecs.umich.edu if kwargs: 8607777Sgblack@eecs.umich.edu if not 'ip' in kwargs and not 'port' in kwargs: 8617777Sgblack@eecs.umich.edu raise TypeError, "Invalid arguments" 8627777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 8637777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'port', args[0]) 8647777Sgblack@eecs.umich.edu elif isinstance(args[0], IpWithPort): 8657777Sgblack@eecs.umich.edu self.ip = args[0].ip 8667777Sgblack@eecs.umich.edu self.port = args[0].port 8677777Sgblack@eecs.umich.edu else: 8687777Sgblack@eecs.umich.edu (self.ip, self.port) = convert.toIpWithPort(args[0]) 8697777Sgblack@eecs.umich.edu 8707777Sgblack@eecs.umich.edu elif len(args) == 2: 8717777Sgblack@eecs.umich.edu self.ip = args[0] 8727777Sgblack@eecs.umich.edu self.port = args[1] 8737777Sgblack@eecs.umich.edu else: 8747777Sgblack@eecs.umich.edu raise TypeError, "Too many arguments specified" 8757777Sgblack@eecs.umich.edu 8767777Sgblack@eecs.umich.edu if kwargs: 8777777Sgblack@eecs.umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 8787777Sgblack@eecs.umich.edu 8797777Sgblack@eecs.umich.edu self.verify() 8807777Sgblack@eecs.umich.edu 8818579Ssteve.reinhardt@amd.com def __str__(self): 8828579Ssteve.reinhardt@amd.com return "%s:%d" % (super(IpWithPort, self).__str__(), self.port) 8838579Ssteve.reinhardt@amd.com 8848579Ssteve.reinhardt@amd.com def __eq__(self, other): 8858579Ssteve.reinhardt@amd.com if isinstance(other, IpWithPort): 8868579Ssteve.reinhardt@amd.com return self.ip == other.ip and self.port == other.port 8878579Ssteve.reinhardt@amd.com elif isinstance(other, str): 8888579Ssteve.reinhardt@amd.com try: 8898579Ssteve.reinhardt@amd.com return (self.ip, self.port) == convert.toIpWithPort(other) 8908579Ssteve.reinhardt@amd.com except: 8918579Ssteve.reinhardt@amd.com return False 8928579Ssteve.reinhardt@amd.com else: 8938579Ssteve.reinhardt@amd.com return False 8948579Ssteve.reinhardt@amd.com 8957777Sgblack@eecs.umich.edu def verify(self): 8967777Sgblack@eecs.umich.edu self.verifyIp() 8977777Sgblack@eecs.umich.edu if self.port < 0 or self.port > 0xffff: 8987777Sgblack@eecs.umich.edu raise TypeError, "invalid port %d" % self.port 8997777Sgblack@eecs.umich.edu 9007777Sgblack@eecs.umich.edu def getValue(self): 9017777Sgblack@eecs.umich.edu from m5.internal.params import IpWithPort 9027777Sgblack@eecs.umich.edu return IpWithPort(self.ip, self.port) 9037777Sgblack@eecs.umich.edu 9043932Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 9053932Sbinkertn@umich.edu "%a %b %d %H:%M:%S %Z %Y", 9063932Sbinkertn@umich.edu "%Y/%m/%d %H:%M:%S", 9073932Sbinkertn@umich.edu "%Y/%m/%d %H:%M", 9083932Sbinkertn@umich.edu "%Y/%m/%d", 9093932Sbinkertn@umich.edu "%m/%d/%Y %H:%M:%S", 9103932Sbinkertn@umich.edu "%m/%d/%Y %H:%M", 9113932Sbinkertn@umich.edu "%m/%d/%Y", 9123932Sbinkertn@umich.edu "%m/%d/%y %H:%M:%S", 9133932Sbinkertn@umich.edu "%m/%d/%y %H:%M", 9143932Sbinkertn@umich.edu "%m/%d/%y"] 9153932Sbinkertn@umich.edu 9163932Sbinkertn@umich.edu 9173885Sbinkertn@umich.edudef parse_time(value): 9183932Sbinkertn@umich.edu from time import gmtime, strptime, struct_time, time 9193932Sbinkertn@umich.edu from datetime import datetime, date 9203885Sbinkertn@umich.edu 9213932Sbinkertn@umich.edu if isinstance(value, struct_time): 9223932Sbinkertn@umich.edu return value 9233932Sbinkertn@umich.edu 9243932Sbinkertn@umich.edu if isinstance(value, (int, long)): 9253932Sbinkertn@umich.edu return gmtime(value) 9263932Sbinkertn@umich.edu 9273932Sbinkertn@umich.edu if isinstance(value, (datetime, date)): 9283932Sbinkertn@umich.edu return value.timetuple() 9293932Sbinkertn@umich.edu 9303932Sbinkertn@umich.edu if isinstance(value, str): 9313932Sbinkertn@umich.edu if value in ('Now', 'Today'): 9323932Sbinkertn@umich.edu return time.gmtime(time.time()) 9333932Sbinkertn@umich.edu 9343932Sbinkertn@umich.edu for format in time_formats: 9353932Sbinkertn@umich.edu try: 9363932Sbinkertn@umich.edu return strptime(value, format) 9373932Sbinkertn@umich.edu except ValueError: 9383932Sbinkertn@umich.edu pass 9393885Sbinkertn@umich.edu 9403885Sbinkertn@umich.edu raise ValueError, "Could not parse '%s' as a time" % value 9413885Sbinkertn@umich.edu 9423885Sbinkertn@umich.educlass Time(ParamValue): 9434762Snate@binkert.org cxx_type = 'tm' 9447673Snate@binkert.org 9457673Snate@binkert.org @classmethod 9467673Snate@binkert.org def cxx_predecls(cls, code): 9477673Snate@binkert.org code('#include <time.h>') 9487673Snate@binkert.org 9497673Snate@binkert.org @classmethod 9507673Snate@binkert.org def swig_predecls(cls, code): 9517673Snate@binkert.org code('%include "python/swig/time.i"') 9527673Snate@binkert.org 9533885Sbinkertn@umich.edu def __init__(self, value): 9543932Sbinkertn@umich.edu self.value = parse_time(value) 9553885Sbinkertn@umich.edu 9564762Snate@binkert.org def getValue(self): 9577677Snate@binkert.org from m5.internal.params import tm 9584762Snate@binkert.org 9594762Snate@binkert.org c_time = tm() 9604762Snate@binkert.org py_time = self.value 9614762Snate@binkert.org 9624762Snate@binkert.org # UNIX is years since 1900 9634762Snate@binkert.org c_time.tm_year = py_time.tm_year - 1900; 9644762Snate@binkert.org 9654762Snate@binkert.org # Python starts at 1, UNIX starts at 0 9664762Snate@binkert.org c_time.tm_mon = py_time.tm_mon - 1; 9674762Snate@binkert.org c_time.tm_mday = py_time.tm_mday; 9684762Snate@binkert.org c_time.tm_hour = py_time.tm_hour; 9694762Snate@binkert.org c_time.tm_min = py_time.tm_min; 9704762Snate@binkert.org c_time.tm_sec = py_time.tm_sec; 9714762Snate@binkert.org 9724762Snate@binkert.org # Python has 0 as Monday, UNIX is 0 as sunday 9734762Snate@binkert.org c_time.tm_wday = py_time.tm_wday + 1 9744762Snate@binkert.org if c_time.tm_wday > 6: 9754762Snate@binkert.org c_time.tm_wday -= 7; 9764762Snate@binkert.org 9774762Snate@binkert.org # Python starts at 1, Unix starts at 0 9784762Snate@binkert.org c_time.tm_yday = py_time.tm_yday - 1; 9794762Snate@binkert.org 9804762Snate@binkert.org return c_time 9814762Snate@binkert.org 9823885Sbinkertn@umich.edu def __str__(self): 9834762Snate@binkert.org return time.asctime(self.value) 9843885Sbinkertn@umich.edu 9853885Sbinkertn@umich.edu def ini_str(self): 9863932Sbinkertn@umich.edu return str(self) 9873885Sbinkertn@umich.edu 9888664SAli.Saidi@ARM.com def get_config_as_dict(self): 9898664SAli.Saidi@ARM.com return str(self) 9908664SAli.Saidi@ARM.com 9913101Sstever@eecs.umich.edu# Enumerated types are a little more complex. The user specifies the 9923101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of 9933101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so). (In the 9943101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index 9953101Sstever@eecs.umich.edu# or the corresponding dictionary value. For now, since we only check 9963101Sstever@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file, 9973101Sstever@eecs.umich.edu# there's not much point in using the dictionary.) 9983101Sstever@eecs.umich.edu 9993101Sstever@eecs.umich.edu# What Enum() must do is generate a new type encapsulating the 10003101Sstever@eecs.umich.edu# provided list/dictionary so that specific values of the parameter 10013101Sstever@eecs.umich.edu# can be instances of that type. We define two hidden internal 10023101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then 10033101Sstever@eecs.umich.edu# derive the new type from the appropriate base class on the fly. 10043101Sstever@eecs.umich.edu 10054762Snate@binkert.orgallEnums = {} 10063101Sstever@eecs.umich.edu# Metaclass for Enum types 10075033Smilesck@eecs.umich.educlass MetaEnum(MetaParamValue): 10084762Snate@binkert.org def __new__(mcls, name, bases, dict): 10094762Snate@binkert.org assert name not in allEnums 10104762Snate@binkert.org 10114762Snate@binkert.org cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 10124762Snate@binkert.org allEnums[name] = cls 10134762Snate@binkert.org return cls 10144762Snate@binkert.org 10153101Sstever@eecs.umich.edu def __init__(cls, name, bases, init_dict): 10163101Sstever@eecs.umich.edu if init_dict.has_key('map'): 10173101Sstever@eecs.umich.edu if not isinstance(cls.map, dict): 10183101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'map' " \ 10193101Sstever@eecs.umich.edu "must be of type dict" 10203101Sstever@eecs.umich.edu # build list of value strings from map 10213101Sstever@eecs.umich.edu cls.vals = cls.map.keys() 10223101Sstever@eecs.umich.edu cls.vals.sort() 10233101Sstever@eecs.umich.edu elif init_dict.has_key('vals'): 10243101Sstever@eecs.umich.edu if not isinstance(cls.vals, list): 10253101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'vals' " \ 10263101Sstever@eecs.umich.edu "must be of type list" 10273101Sstever@eecs.umich.edu # build string->value map from vals sequence 10283101Sstever@eecs.umich.edu cls.map = {} 10293101Sstever@eecs.umich.edu for idx,val in enumerate(cls.vals): 10303101Sstever@eecs.umich.edu cls.map[val] = idx 10313101Sstever@eecs.umich.edu else: 10323101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class must define "\ 10333101Sstever@eecs.umich.edu "attribute 'map' or 'vals'" 10343101Sstever@eecs.umich.edu 10354762Snate@binkert.org cls.cxx_type = 'Enums::%s' % name 10363101Sstever@eecs.umich.edu 10373101Sstever@eecs.umich.edu super(MetaEnum, cls).__init__(name, bases, init_dict) 10383101Sstever@eecs.umich.edu 10393101Sstever@eecs.umich.edu # Generate C++ class declaration for this enum type. 10403101Sstever@eecs.umich.edu # Note that we wrap the enum in a class/struct to act as a namespace, 10413101Sstever@eecs.umich.edu # so that the enum strings can be brief w/o worrying about collisions. 10427673Snate@binkert.org def cxx_decl(cls, code): 104310201SAndrew.Bardsley@arm.com wrapper_name = cls.wrapper_name 104410201SAndrew.Bardsley@arm.com wrapper = 'struct' if cls.wrapper_is_struct else 'namespace' 104510201SAndrew.Bardsley@arm.com name = cls.__name__ if cls.enum_name is None else cls.enum_name 104610201SAndrew.Bardsley@arm.com idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name) 104710201SAndrew.Bardsley@arm.com 10487673Snate@binkert.org code('''\ 104910201SAndrew.Bardsley@arm.com#ifndef $idem_macro 105010201SAndrew.Bardsley@arm.com#define $idem_macro 10517673Snate@binkert.org 105210201SAndrew.Bardsley@arm.com$wrapper $wrapper_name { 10537673Snate@binkert.org enum $name { 10547673Snate@binkert.org''') 10557673Snate@binkert.org code.indent(2) 10564762Snate@binkert.org for val in cls.vals: 10577673Snate@binkert.org code('$val = ${{cls.map[val]}},') 10588902Sandreas.hansson@arm.com code('Num_$name = ${{len(cls.vals)}}') 10597673Snate@binkert.org code.dedent(2) 106010201SAndrew.Bardsley@arm.com code(' };') 10614762Snate@binkert.org 106210201SAndrew.Bardsley@arm.com if cls.wrapper_is_struct: 106310201SAndrew.Bardsley@arm.com code(' static const char *${name}Strings[Num_${name}];') 106410201SAndrew.Bardsley@arm.com code('};') 106510201SAndrew.Bardsley@arm.com else: 106610201SAndrew.Bardsley@arm.com code('extern const char *${name}Strings[Num_${name}];') 106710201SAndrew.Bardsley@arm.com code('}') 106810201SAndrew.Bardsley@arm.com 106910201SAndrew.Bardsley@arm.com code() 107010201SAndrew.Bardsley@arm.com code('#endif // $idem_macro') 10717673Snate@binkert.org 10727673Snate@binkert.org def cxx_def(cls, code): 107310201SAndrew.Bardsley@arm.com wrapper_name = cls.wrapper_name 107410201SAndrew.Bardsley@arm.com file_name = cls.__name__ 107510201SAndrew.Bardsley@arm.com name = cls.__name__ if cls.enum_name is None else cls.enum_name 107610201SAndrew.Bardsley@arm.com 107710201SAndrew.Bardsley@arm.com code('#include "enums/$file_name.hh"') 107810201SAndrew.Bardsley@arm.com if cls.wrapper_is_struct: 107910201SAndrew.Bardsley@arm.com code('const char *${wrapper_name}::${name}Strings' 108010201SAndrew.Bardsley@arm.com '[Num_${name}] =') 108110201SAndrew.Bardsley@arm.com else: 108210201SAndrew.Bardsley@arm.com code('namespace Enums {') 108310201SAndrew.Bardsley@arm.com code.indent(1) 108410201SAndrew.Bardsley@arm.com code(' const char *${name}Strings[Num_${name}] =') 108510201SAndrew.Bardsley@arm.com 108610201SAndrew.Bardsley@arm.com code('{') 108710201SAndrew.Bardsley@arm.com code.indent(1) 10884762Snate@binkert.org for val in cls.vals: 10897673Snate@binkert.org code('"$val",') 109010201SAndrew.Bardsley@arm.com code.dedent(1) 109110201SAndrew.Bardsley@arm.com code('};') 109210201SAndrew.Bardsley@arm.com 109310201SAndrew.Bardsley@arm.com if not cls.wrapper_is_struct: 109410201SAndrew.Bardsley@arm.com code('} // namespace $wrapper_name') 109510201SAndrew.Bardsley@arm.com code.dedent(1) 10963101Sstever@eecs.umich.edu 10978596Ssteve.reinhardt@amd.com def swig_decl(cls, code): 10988596Ssteve.reinhardt@amd.com name = cls.__name__ 10998596Ssteve.reinhardt@amd.com code('''\ 11008596Ssteve.reinhardt@amd.com%module(package="m5.internal") enum_$name 11018596Ssteve.reinhardt@amd.com 11028596Ssteve.reinhardt@amd.com%{ 11038596Ssteve.reinhardt@amd.com#include "enums/$name.hh" 11048596Ssteve.reinhardt@amd.com%} 11058596Ssteve.reinhardt@amd.com 11068596Ssteve.reinhardt@amd.com%include "enums/$name.hh" 11078596Ssteve.reinhardt@amd.com''') 11088596Ssteve.reinhardt@amd.com 11098596Ssteve.reinhardt@amd.com 11103101Sstever@eecs.umich.edu# Base class for enum types. 11113101Sstever@eecs.umich.educlass Enum(ParamValue): 11123101Sstever@eecs.umich.edu __metaclass__ = MetaEnum 11133101Sstever@eecs.umich.edu vals = [] 11143101Sstever@eecs.umich.edu 111510201SAndrew.Bardsley@arm.com # The name of the wrapping namespace or struct 111610201SAndrew.Bardsley@arm.com wrapper_name = 'Enums' 111710201SAndrew.Bardsley@arm.com 111810201SAndrew.Bardsley@arm.com # If true, the enum is wrapped in a struct rather than a namespace 111910201SAndrew.Bardsley@arm.com wrapper_is_struct = False 112010201SAndrew.Bardsley@arm.com 112110201SAndrew.Bardsley@arm.com # If not None, use this as the enum name rather than this class name 112210201SAndrew.Bardsley@arm.com enum_name = None 112310201SAndrew.Bardsley@arm.com 11243101Sstever@eecs.umich.edu def __init__(self, value): 11253101Sstever@eecs.umich.edu if value not in self.map: 11263101Sstever@eecs.umich.edu raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 11273101Sstever@eecs.umich.edu % (value, self.vals) 11283101Sstever@eecs.umich.edu self.value = value 11293101Sstever@eecs.umich.edu 11307675Snate@binkert.org @classmethod 11317675Snate@binkert.org def cxx_predecls(cls, code): 11327675Snate@binkert.org code('#include "enums/$0.hh"', cls.__name__) 11337675Snate@binkert.org 11347675Snate@binkert.org @classmethod 11357675Snate@binkert.org def swig_predecls(cls, code): 11367677Snate@binkert.org code('%import "python/m5/internal/enum_$0.i"', cls.__name__) 11377675Snate@binkert.org 11384762Snate@binkert.org def getValue(self): 11394762Snate@binkert.org return int(self.map[self.value]) 11404762Snate@binkert.org 11413101Sstever@eecs.umich.edu def __str__(self): 11423101Sstever@eecs.umich.edu return self.value 11433101Sstever@eecs.umich.edu 11443101Sstever@eecs.umich.edu# how big does a rounding error need to be before we warn about it? 11453101Sstever@eecs.umich.edufrequency_tolerance = 0.001 # 0.1% 11463101Sstever@eecs.umich.edu 11474167Sbinkertn@umich.educlass TickParamValue(NumericParamValue): 11483101Sstever@eecs.umich.edu cxx_type = 'Tick' 11497673Snate@binkert.org 11507673Snate@binkert.org @classmethod 11517673Snate@binkert.org def cxx_predecls(cls, code): 11527673Snate@binkert.org code('#include "base/types.hh"') 11537673Snate@binkert.org 11547673Snate@binkert.org @classmethod 11557673Snate@binkert.org def swig_predecls(cls, code): 11567673Snate@binkert.org code('%import "stdint.i"') 11577673Snate@binkert.org code('%import "base/types.hh"') 11584167Sbinkertn@umich.edu 11594762Snate@binkert.org def getValue(self): 11604762Snate@binkert.org return long(self.value) 11614762Snate@binkert.org 11624167Sbinkertn@umich.educlass Latency(TickParamValue): 11633101Sstever@eecs.umich.edu def __init__(self, value): 11644167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 11654167Sbinkertn@umich.edu self.ticks = value.ticks 11664167Sbinkertn@umich.edu self.value = value.value 11674167Sbinkertn@umich.edu elif isinstance(value, Frequency): 11684167Sbinkertn@umich.edu self.ticks = value.ticks 11694167Sbinkertn@umich.edu self.value = 1.0 / value.value 11704167Sbinkertn@umich.edu elif value.endswith('t'): 11714167Sbinkertn@umich.edu self.ticks = True 11724167Sbinkertn@umich.edu self.value = int(value[:-1]) 11734167Sbinkertn@umich.edu else: 11744167Sbinkertn@umich.edu self.ticks = False 11754167Sbinkertn@umich.edu self.value = convert.toLatency(value) 11763101Sstever@eecs.umich.edu 11773101Sstever@eecs.umich.edu def __getattr__(self, attr): 11783101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 11793101Sstever@eecs.umich.edu return self 11803101Sstever@eecs.umich.edu if attr == 'frequency': 11813101Sstever@eecs.umich.edu return Frequency(self) 11823101Sstever@eecs.umich.edu raise AttributeError, "Latency object has no attribute '%s'" % attr 11833101Sstever@eecs.umich.edu 11844762Snate@binkert.org def getValue(self): 11854762Snate@binkert.org if self.ticks or self.value == 0: 11864762Snate@binkert.org value = self.value 11874762Snate@binkert.org else: 11884762Snate@binkert.org value = ticks.fromSeconds(self.value) 11894762Snate@binkert.org return long(value) 11904762Snate@binkert.org 11913101Sstever@eecs.umich.edu # convert latency to ticks 11923101Sstever@eecs.umich.edu def ini_str(self): 11934762Snate@binkert.org return '%d' % self.getValue() 11943101Sstever@eecs.umich.edu 11954167Sbinkertn@umich.educlass Frequency(TickParamValue): 11963101Sstever@eecs.umich.edu def __init__(self, value): 11974167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 11984167Sbinkertn@umich.edu if value.value == 0: 11994167Sbinkertn@umich.edu self.value = 0 12004167Sbinkertn@umich.edu else: 12014167Sbinkertn@umich.edu self.value = 1.0 / value.value 12024167Sbinkertn@umich.edu self.ticks = value.ticks 12034167Sbinkertn@umich.edu elif isinstance(value, Frequency): 12044167Sbinkertn@umich.edu self.value = value.value 12054167Sbinkertn@umich.edu self.ticks = value.ticks 12064167Sbinkertn@umich.edu else: 12074167Sbinkertn@umich.edu self.ticks = False 12084167Sbinkertn@umich.edu self.value = convert.toFrequency(value) 12093101Sstever@eecs.umich.edu 12103101Sstever@eecs.umich.edu def __getattr__(self, attr): 12113101Sstever@eecs.umich.edu if attr == 'frequency': 12123101Sstever@eecs.umich.edu return self 12133101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 12143101Sstever@eecs.umich.edu return Latency(self) 12153101Sstever@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 12163101Sstever@eecs.umich.edu 12174167Sbinkertn@umich.edu # convert latency to ticks 12184762Snate@binkert.org def getValue(self): 12194762Snate@binkert.org if self.ticks or self.value == 0: 12204762Snate@binkert.org value = self.value 12214762Snate@binkert.org else: 12224762Snate@binkert.org value = ticks.fromSeconds(1.0 / self.value) 12234762Snate@binkert.org return long(value) 12244762Snate@binkert.org 12253101Sstever@eecs.umich.edu def ini_str(self): 12264762Snate@binkert.org return '%d' % self.getValue() 12273101Sstever@eecs.umich.edu 122810019Sandreas.hansson@arm.com# A generic Frequency and/or Latency value. Value is stored as a 122910019Sandreas.hansson@arm.com# latency, just like Latency and Frequency. 123010019Sandreas.hansson@arm.comclass Clock(TickParamValue): 12313101Sstever@eecs.umich.edu def __init__(self, value): 12324167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 12334167Sbinkertn@umich.edu self.ticks = value.ticks 12344167Sbinkertn@umich.edu self.value = value.value 12354167Sbinkertn@umich.edu elif isinstance(value, Frequency): 12364167Sbinkertn@umich.edu self.ticks = value.ticks 12374167Sbinkertn@umich.edu self.value = 1.0 / value.value 12384167Sbinkertn@umich.edu elif value.endswith('t'): 12394167Sbinkertn@umich.edu self.ticks = True 12404167Sbinkertn@umich.edu self.value = int(value[:-1]) 12414167Sbinkertn@umich.edu else: 12424167Sbinkertn@umich.edu self.ticks = False 12434167Sbinkertn@umich.edu self.value = convert.anyToLatency(value) 12443101Sstever@eecs.umich.edu 12453101Sstever@eecs.umich.edu def __getattr__(self, attr): 12463101Sstever@eecs.umich.edu if attr == 'frequency': 12473101Sstever@eecs.umich.edu return Frequency(self) 12483101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 12493101Sstever@eecs.umich.edu return Latency(self) 12503101Sstever@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 12513101Sstever@eecs.umich.edu 12524762Snate@binkert.org def getValue(self): 12534762Snate@binkert.org return self.period.getValue() 12544762Snate@binkert.org 12553101Sstever@eecs.umich.edu def ini_str(self): 12563101Sstever@eecs.umich.edu return self.period.ini_str() 12573101Sstever@eecs.umich.edu 12589827Sakash.bagdia@arm.comclass Voltage(float,ParamValue): 12599827Sakash.bagdia@arm.com cxx_type = 'double' 12609827Sakash.bagdia@arm.com def __new__(cls, value): 12619827Sakash.bagdia@arm.com # convert to voltage 12629827Sakash.bagdia@arm.com val = convert.toVoltage(value) 12639827Sakash.bagdia@arm.com return super(cls, Voltage).__new__(cls, val) 12649827Sakash.bagdia@arm.com 12659827Sakash.bagdia@arm.com def __str__(self): 12669827Sakash.bagdia@arm.com return str(self.val) 12679827Sakash.bagdia@arm.com 12689827Sakash.bagdia@arm.com def getValue(self): 12699827Sakash.bagdia@arm.com value = float(self) 12709827Sakash.bagdia@arm.com return value 12719827Sakash.bagdia@arm.com 12729827Sakash.bagdia@arm.com def ini_str(self): 12739827Sakash.bagdia@arm.com return '%f' % self.getValue() 12749827Sakash.bagdia@arm.com 12753101Sstever@eecs.umich.educlass NetworkBandwidth(float,ParamValue): 12763101Sstever@eecs.umich.edu cxx_type = 'float' 12773101Sstever@eecs.umich.edu def __new__(cls, value): 12784167Sbinkertn@umich.edu # convert to bits per second 12794167Sbinkertn@umich.edu val = convert.toNetworkBandwidth(value) 12803101Sstever@eecs.umich.edu return super(cls, NetworkBandwidth).__new__(cls, val) 12813101Sstever@eecs.umich.edu 12823101Sstever@eecs.umich.edu def __str__(self): 12833101Sstever@eecs.umich.edu return str(self.val) 12843101Sstever@eecs.umich.edu 12854762Snate@binkert.org def getValue(self): 12864167Sbinkertn@umich.edu # convert to seconds per byte 12874167Sbinkertn@umich.edu value = 8.0 / float(self) 12884167Sbinkertn@umich.edu # convert to ticks per byte 12894762Snate@binkert.org value = ticks.fromSeconds(value) 12904762Snate@binkert.org return float(value) 12914762Snate@binkert.org 12924762Snate@binkert.org def ini_str(self): 12934762Snate@binkert.org return '%f' % self.getValue() 12943101Sstever@eecs.umich.edu 12953101Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue): 12963101Sstever@eecs.umich.edu cxx_type = 'float' 12975469Snate@binkert.org def __new__(cls, value): 12987743Sgblack@eecs.umich.edu # convert to bytes per second 12993102Sstever@eecs.umich.edu val = convert.toMemoryBandwidth(value) 13003101Sstever@eecs.umich.edu return super(cls, MemoryBandwidth).__new__(cls, val) 13013101Sstever@eecs.umich.edu 13023101Sstever@eecs.umich.edu def __str__(self): 13033101Sstever@eecs.umich.edu return str(self.val) 13043101Sstever@eecs.umich.edu 13054762Snate@binkert.org def getValue(self): 13064167Sbinkertn@umich.edu # convert to seconds per byte 13075468Snate@binkert.org value = float(self) 13085468Snate@binkert.org if value: 13095468Snate@binkert.org value = 1.0 / float(self) 13104167Sbinkertn@umich.edu # convert to ticks per byte 13114762Snate@binkert.org value = ticks.fromSeconds(value) 13124762Snate@binkert.org return float(value) 13134762Snate@binkert.org 13144762Snate@binkert.org def ini_str(self): 13154762Snate@binkert.org return '%f' % self.getValue() 13163101Sstever@eecs.umich.edu 13173101Sstever@eecs.umich.edu# 13183101Sstever@eecs.umich.edu# "Constants"... handy aliases for various values. 13193101Sstever@eecs.umich.edu# 13203101Sstever@eecs.umich.edu 13213102Sstever@eecs.umich.edu# Special class for NULL pointers. Note the special check in 13223102Sstever@eecs.umich.edu# make_param_value() above that lets these be assigned where a 13233102Sstever@eecs.umich.edu# SimObject is required. 13243102Sstever@eecs.umich.edu# only one copy of a particular node 13253102Sstever@eecs.umich.educlass NullSimObject(object): 13263102Sstever@eecs.umich.edu __metaclass__ = Singleton 13273102Sstever@eecs.umich.edu 13283102Sstever@eecs.umich.edu def __call__(cls): 13293102Sstever@eecs.umich.edu return cls 13303102Sstever@eecs.umich.edu 13313102Sstever@eecs.umich.edu def _instantiate(self, parent = None, path = ''): 13323102Sstever@eecs.umich.edu pass 13333102Sstever@eecs.umich.edu 13343102Sstever@eecs.umich.edu def ini_str(self): 13353102Sstever@eecs.umich.edu return 'Null' 13363102Sstever@eecs.umich.edu 13373102Sstever@eecs.umich.edu def unproxy(self, base): 13383102Sstever@eecs.umich.edu return self 13393102Sstever@eecs.umich.edu 13403102Sstever@eecs.umich.edu def set_path(self, parent, name): 13413102Sstever@eecs.umich.edu pass 13424762Snate@binkert.org 13433102Sstever@eecs.umich.edu def __str__(self): 13443102Sstever@eecs.umich.edu return 'Null' 13453102Sstever@eecs.umich.edu 13464762Snate@binkert.org def getValue(self): 13474762Snate@binkert.org return None 13484762Snate@binkert.org 13493102Sstever@eecs.umich.edu# The only instance you'll ever need... 13503102Sstever@eecs.umich.eduNULL = NullSimObject() 13513102Sstever@eecs.umich.edu 13523102Sstever@eecs.umich.edudef isNullPointer(value): 13533102Sstever@eecs.umich.edu return isinstance(value, NullSimObject) 13543102Sstever@eecs.umich.edu 13553101Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound. 13563101Sstever@eecs.umich.eduMaxAddr = Addr.max 13573101Sstever@eecs.umich.eduMaxTick = Tick.max 13583101Sstever@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr) 13593101Sstever@eecs.umich.edu 13603101Sstever@eecs.umich.edu 13613101Sstever@eecs.umich.edu##################################################################### 13623101Sstever@eecs.umich.edu# 13633101Sstever@eecs.umich.edu# Port objects 13643101Sstever@eecs.umich.edu# 13653101Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system. 13663101Sstever@eecs.umich.edu# 13673101Sstever@eecs.umich.edu##################################################################### 13683101Sstever@eecs.umich.edu 13693101Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a 13703101Sstever@eecs.umich.edu# particular SimObject. 13713101Sstever@eecs.umich.educlass PortRef(object): 13728839Sandreas.hansson@arm.com def __init__(self, simobj, name, role): 13733105Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 13743101Sstever@eecs.umich.edu self.simobj = simobj 13753101Sstever@eecs.umich.edu self.name = name 13768839Sandreas.hansson@arm.com self.role = role 13773101Sstever@eecs.umich.edu self.peer = None # not associated with another port yet 13783101Sstever@eecs.umich.edu self.ccConnected = False # C++ port connection done? 13793105Sstever@eecs.umich.edu self.index = -1 # always -1 for non-vector ports 13803101Sstever@eecs.umich.edu 13813103Sstever@eecs.umich.edu def __str__(self): 13823105Sstever@eecs.umich.edu return '%s.%s' % (self.simobj, self.name) 13833103Sstever@eecs.umich.edu 13848840Sandreas.hansson@arm.com def __len__(self): 13858840Sandreas.hansson@arm.com # Return the number of connected ports, i.e. 0 is we have no 13868840Sandreas.hansson@arm.com # peer and 1 if we do. 13878840Sandreas.hansson@arm.com return int(self.peer != None) 13888840Sandreas.hansson@arm.com 13893105Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 13903105Sstever@eecs.umich.edu def ini_str(self): 13913105Sstever@eecs.umich.edu return str(self.peer) 13923105Sstever@eecs.umich.edu 13939017Sandreas.hansson@arm.com # for config.json 13949017Sandreas.hansson@arm.com def get_config_as_dict(self): 13959017Sandreas.hansson@arm.com return {'role' : self.role, 'peer' : str(self.peer)} 13969017Sandreas.hansson@arm.com 13973105Sstever@eecs.umich.edu def __getattr__(self, attr): 13983105Sstever@eecs.umich.edu if attr == 'peerObj': 13993105Sstever@eecs.umich.edu # shorthand for proxies 14003105Sstever@eecs.umich.edu return self.peer.simobj 14013105Sstever@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 14023105Sstever@eecs.umich.edu (self.__class__.__name__, attr) 14033105Sstever@eecs.umich.edu 14043105Sstever@eecs.umich.edu # Full connection is symmetric (both ways). Called via 14053105Sstever@eecs.umich.edu # SimObject.__setattr__ as a result of a port assignment, e.g., 14063109Sstever@eecs.umich.edu # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 14073105Sstever@eecs.umich.edu # e.g., "obj1.portA[3] = obj2.portB". 14083105Sstever@eecs.umich.edu def connect(self, other): 14093105Sstever@eecs.umich.edu if isinstance(other, VectorPortRef): 14103105Sstever@eecs.umich.edu # reference to plain VectorPort is implicit append 14113105Sstever@eecs.umich.edu other = other._get_next() 14123105Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 14139014Sandreas.hansson@arm.com fatal("Port %s is already connected to %s, cannot connect %s\n", 14149014Sandreas.hansson@arm.com self, self.peer, other); 14153101Sstever@eecs.umich.edu self.peer = other 14163109Sstever@eecs.umich.edu if proxy.isproxy(other): 14173109Sstever@eecs.umich.edu other.set_param_desc(PortParamDesc()) 14183109Sstever@eecs.umich.edu elif isinstance(other, PortRef): 14193109Sstever@eecs.umich.edu if other.peer is not self: 14203109Sstever@eecs.umich.edu other.connect(self) 14213109Sstever@eecs.umich.edu else: 14223109Sstever@eecs.umich.edu raise TypeError, \ 14233109Sstever@eecs.umich.edu "assigning non-port reference '%s' to port '%s'" \ 14243109Sstever@eecs.umich.edu % (other, self) 14253101Sstever@eecs.umich.edu 14263105Sstever@eecs.umich.edu def clone(self, simobj, memo): 14273105Sstever@eecs.umich.edu if memo.has_key(self): 14283105Sstever@eecs.umich.edu return memo[self] 14293101Sstever@eecs.umich.edu newRef = copy.copy(self) 14303105Sstever@eecs.umich.edu memo[self] = newRef 14313105Sstever@eecs.umich.edu newRef.simobj = simobj 14323101Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 14333105Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 14343179Sstever@eecs.umich.edu peerObj = self.peer.simobj(_memo=memo) 14353105Sstever@eecs.umich.edu newRef.peer = self.peer.clone(peerObj, memo) 14363105Sstever@eecs.umich.edu assert(not isinstance(newRef.peer, VectorPortRef)) 14373101Sstever@eecs.umich.edu return newRef 14383101Sstever@eecs.umich.edu 14393105Sstever@eecs.umich.edu def unproxy(self, simobj): 14403105Sstever@eecs.umich.edu assert(simobj is self.simobj) 14413105Sstever@eecs.umich.edu if proxy.isproxy(self.peer): 14423105Sstever@eecs.umich.edu try: 14433105Sstever@eecs.umich.edu realPeer = self.peer.unproxy(self.simobj) 14443105Sstever@eecs.umich.edu except: 14453105Sstever@eecs.umich.edu print "Error in unproxying port '%s' of %s" % \ 14463105Sstever@eecs.umich.edu (self.name, self.simobj.path()) 14473105Sstever@eecs.umich.edu raise 14483105Sstever@eecs.umich.edu self.connect(realPeer) 14493105Sstever@eecs.umich.edu 14503101Sstever@eecs.umich.edu # Call C++ to create corresponding port connection between C++ objects 14513101Sstever@eecs.umich.edu def ccConnect(self): 14528597Ssteve.reinhardt@amd.com from m5.internal.pyobject import connectPorts 14534762Snate@binkert.org 14548839Sandreas.hansson@arm.com if self.role == 'SLAVE': 14558839Sandreas.hansson@arm.com # do nothing and let the master take care of it 14568839Sandreas.hansson@arm.com return 14578839Sandreas.hansson@arm.com 14583101Sstever@eecs.umich.edu if self.ccConnected: # already done this 14593101Sstever@eecs.umich.edu return 14603101Sstever@eecs.umich.edu peer = self.peer 14615578SSteve.Reinhardt@amd.com if not self.peer: # nothing to connect to 14625578SSteve.Reinhardt@amd.com return 14638839Sandreas.hansson@arm.com 14648839Sandreas.hansson@arm.com # check that we connect a master to a slave 14658839Sandreas.hansson@arm.com if self.role == peer.role: 14668839Sandreas.hansson@arm.com raise TypeError, \ 14678839Sandreas.hansson@arm.com "cannot connect '%s' and '%s' due to identical role '%s'" \ 14688839Sandreas.hansson@arm.com % (peer, self, self.role) 14698839Sandreas.hansson@arm.com 14707526Ssteve.reinhardt@amd.com try: 14718839Sandreas.hansson@arm.com # self is always the master and peer the slave 14727526Ssteve.reinhardt@amd.com connectPorts(self.simobj.getCCObject(), self.name, self.index, 14737526Ssteve.reinhardt@amd.com peer.simobj.getCCObject(), peer.name, peer.index) 14747526Ssteve.reinhardt@amd.com except: 14757526Ssteve.reinhardt@amd.com print "Error connecting port %s.%s to %s.%s" % \ 14767526Ssteve.reinhardt@amd.com (self.simobj.path(), self.name, 14777526Ssteve.reinhardt@amd.com peer.simobj.path(), peer.name) 14787526Ssteve.reinhardt@amd.com raise 14793101Sstever@eecs.umich.edu self.ccConnected = True 14803101Sstever@eecs.umich.edu peer.ccConnected = True 14813101Sstever@eecs.umich.edu 14823105Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a 14833105Sstever@eecs.umich.edu# PortRef, but has an index. 14843105Sstever@eecs.umich.educlass VectorPortElementRef(PortRef): 14858839Sandreas.hansson@arm.com def __init__(self, simobj, name, role, index): 14868839Sandreas.hansson@arm.com PortRef.__init__(self, simobj, name, role) 14873105Sstever@eecs.umich.edu self.index = index 14883105Sstever@eecs.umich.edu 14893105Sstever@eecs.umich.edu def __str__(self): 14903105Sstever@eecs.umich.edu return '%s.%s[%d]' % (self.simobj, self.name, self.index) 14913105Sstever@eecs.umich.edu 14923105Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element). 14933105Sstever@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances. 14943105Sstever@eecs.umich.educlass VectorPortRef(object): 14958839Sandreas.hansson@arm.com def __init__(self, simobj, name, role): 14963105Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 14973105Sstever@eecs.umich.edu self.simobj = simobj 14983105Sstever@eecs.umich.edu self.name = name 14998839Sandreas.hansson@arm.com self.role = role 15003105Sstever@eecs.umich.edu self.elements = [] 15013105Sstever@eecs.umich.edu 15023109Sstever@eecs.umich.edu def __str__(self): 15033109Sstever@eecs.umich.edu return '%s.%s[:]' % (self.simobj, self.name) 15043109Sstever@eecs.umich.edu 15058840Sandreas.hansson@arm.com def __len__(self): 15068840Sandreas.hansson@arm.com # Return the number of connected peers, corresponding the the 15078840Sandreas.hansson@arm.com # length of the elements. 15088840Sandreas.hansson@arm.com return len(self.elements) 15098840Sandreas.hansson@arm.com 15103105Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 15113105Sstever@eecs.umich.edu def ini_str(self): 15123105Sstever@eecs.umich.edu return ' '.join([el.ini_str() for el in self.elements]) 15133105Sstever@eecs.umich.edu 15149017Sandreas.hansson@arm.com # for config.json 15159017Sandreas.hansson@arm.com def get_config_as_dict(self): 15169017Sandreas.hansson@arm.com return {'role' : self.role, 15179017Sandreas.hansson@arm.com 'peer' : [el.ini_str() for el in self.elements]} 15189017Sandreas.hansson@arm.com 15193105Sstever@eecs.umich.edu def __getitem__(self, key): 15203105Sstever@eecs.umich.edu if not isinstance(key, int): 15213105Sstever@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 15223105Sstever@eecs.umich.edu if key >= len(self.elements): 15233105Sstever@eecs.umich.edu # need to extend list 15248839Sandreas.hansson@arm.com ext = [VectorPortElementRef(self.simobj, self.name, self.role, i) 15253105Sstever@eecs.umich.edu for i in range(len(self.elements), key+1)] 15263105Sstever@eecs.umich.edu self.elements.extend(ext) 15273105Sstever@eecs.umich.edu return self.elements[key] 15283105Sstever@eecs.umich.edu 15293105Sstever@eecs.umich.edu def _get_next(self): 15303105Sstever@eecs.umich.edu return self[len(self.elements)] 15313105Sstever@eecs.umich.edu 15323105Sstever@eecs.umich.edu def __setitem__(self, key, value): 15333105Sstever@eecs.umich.edu if not isinstance(key, int): 15343105Sstever@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 15353105Sstever@eecs.umich.edu self[key].connect(value) 15363105Sstever@eecs.umich.edu 15373105Sstever@eecs.umich.edu def connect(self, other): 15383109Sstever@eecs.umich.edu if isinstance(other, (list, tuple)): 15393109Sstever@eecs.umich.edu # Assign list of port refs to vector port. 15403109Sstever@eecs.umich.edu # For now, append them... not sure if that's the right semantics 15413109Sstever@eecs.umich.edu # or if it should replace the current vector. 15423109Sstever@eecs.umich.edu for ref in other: 15433109Sstever@eecs.umich.edu self._get_next().connect(ref) 15443109Sstever@eecs.umich.edu else: 15453109Sstever@eecs.umich.edu # scalar assignment to plain VectorPort is implicit append 15463109Sstever@eecs.umich.edu self._get_next().connect(other) 15473109Sstever@eecs.umich.edu 15483109Sstever@eecs.umich.edu def clone(self, simobj, memo): 15493109Sstever@eecs.umich.edu if memo.has_key(self): 15503109Sstever@eecs.umich.edu return memo[self] 15513109Sstever@eecs.umich.edu newRef = copy.copy(self) 15523109Sstever@eecs.umich.edu memo[self] = newRef 15533109Sstever@eecs.umich.edu newRef.simobj = simobj 15543109Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 15553109Sstever@eecs.umich.edu newRef.elements = [el.clone(simobj, memo) for el in self.elements] 15563109Sstever@eecs.umich.edu return newRef 15573105Sstever@eecs.umich.edu 15583105Sstever@eecs.umich.edu def unproxy(self, simobj): 15593105Sstever@eecs.umich.edu [el.unproxy(simobj) for el in self.elements] 15603105Sstever@eecs.umich.edu 15613105Sstever@eecs.umich.edu def ccConnect(self): 15623105Sstever@eecs.umich.edu [el.ccConnect() for el in self.elements] 15633105Sstever@eecs.umich.edu 15643101Sstever@eecs.umich.edu# Port description object. Like a ParamDesc object, this represents a 15653101Sstever@eecs.umich.edu# logical port in the SimObject class, not a particular port on a 15663101Sstever@eecs.umich.edu# SimObject instance. The latter are represented by PortRef objects. 15673101Sstever@eecs.umich.educlass Port(object): 15683101Sstever@eecs.umich.edu # Generate a PortRef for this port on the given SimObject with the 15693101Sstever@eecs.umich.edu # given name 15703105Sstever@eecs.umich.edu def makeRef(self, simobj): 15718839Sandreas.hansson@arm.com return PortRef(simobj, self.name, self.role) 15723101Sstever@eecs.umich.edu 15733101Sstever@eecs.umich.edu # Connect an instance of this port (on the given SimObject with 15743101Sstever@eecs.umich.edu # the given name) with the port described by the supplied PortRef 15753105Sstever@eecs.umich.edu def connect(self, simobj, ref): 15763105Sstever@eecs.umich.edu self.makeRef(simobj).connect(ref) 15773101Sstever@eecs.umich.edu 15788840Sandreas.hansson@arm.com # No need for any pre-declarations at the moment as we merely rely 15798840Sandreas.hansson@arm.com # on an unsigned int. 15808840Sandreas.hansson@arm.com def cxx_predecls(self, code): 15818840Sandreas.hansson@arm.com pass 15828840Sandreas.hansson@arm.com 15838840Sandreas.hansson@arm.com # Declare an unsigned int with the same name as the port, that 15848840Sandreas.hansson@arm.com # will eventually hold the number of connected ports (and thus the 15858840Sandreas.hansson@arm.com # number of elements for a VectorPort). 15868840Sandreas.hansson@arm.com def cxx_decl(self, code): 15878840Sandreas.hansson@arm.com code('unsigned int port_${{self.name}}_connection_count;') 15888840Sandreas.hansson@arm.com 15898839Sandreas.hansson@arm.comclass MasterPort(Port): 15908839Sandreas.hansson@arm.com # MasterPort("description") 15918839Sandreas.hansson@arm.com def __init__(self, *args): 15928839Sandreas.hansson@arm.com if len(args) == 1: 15938839Sandreas.hansson@arm.com self.desc = args[0] 15948839Sandreas.hansson@arm.com self.role = 'MASTER' 15958839Sandreas.hansson@arm.com else: 15968839Sandreas.hansson@arm.com raise TypeError, 'wrong number of arguments' 15978839Sandreas.hansson@arm.com 15988839Sandreas.hansson@arm.comclass SlavePort(Port): 15998839Sandreas.hansson@arm.com # SlavePort("description") 16008839Sandreas.hansson@arm.com def __init__(self, *args): 16018839Sandreas.hansson@arm.com if len(args) == 1: 16028839Sandreas.hansson@arm.com self.desc = args[0] 16038839Sandreas.hansson@arm.com self.role = 'SLAVE' 16048839Sandreas.hansson@arm.com else: 16058839Sandreas.hansson@arm.com raise TypeError, 'wrong number of arguments' 16068839Sandreas.hansson@arm.com 16073101Sstever@eecs.umich.edu# VectorPort description object. Like Port, but represents a vector 16083101Sstever@eecs.umich.edu# of connections (e.g., as on a Bus). 16093101Sstever@eecs.umich.educlass VectorPort(Port): 16103105Sstever@eecs.umich.edu def __init__(self, *args): 16113101Sstever@eecs.umich.edu self.isVec = True 16123101Sstever@eecs.umich.edu 16133105Sstever@eecs.umich.edu def makeRef(self, simobj): 16148839Sandreas.hansson@arm.com return VectorPortRef(simobj, self.name, self.role) 16158839Sandreas.hansson@arm.com 16168839Sandreas.hansson@arm.comclass VectorMasterPort(VectorPort): 16178839Sandreas.hansson@arm.com # VectorMasterPort("description") 16188839Sandreas.hansson@arm.com def __init__(self, *args): 16198839Sandreas.hansson@arm.com if len(args) == 1: 16208839Sandreas.hansson@arm.com self.desc = args[0] 16218839Sandreas.hansson@arm.com self.role = 'MASTER' 16228839Sandreas.hansson@arm.com VectorPort.__init__(self, *args) 16238839Sandreas.hansson@arm.com else: 16248839Sandreas.hansson@arm.com raise TypeError, 'wrong number of arguments' 16258839Sandreas.hansson@arm.com 16268839Sandreas.hansson@arm.comclass VectorSlavePort(VectorPort): 16278839Sandreas.hansson@arm.com # VectorSlavePort("description") 16288839Sandreas.hansson@arm.com def __init__(self, *args): 16298839Sandreas.hansson@arm.com if len(args) == 1: 16308839Sandreas.hansson@arm.com self.desc = args[0] 16318839Sandreas.hansson@arm.com self.role = 'SLAVE' 16328839Sandreas.hansson@arm.com VectorPort.__init__(self, *args) 16338839Sandreas.hansson@arm.com else: 16348839Sandreas.hansson@arm.com raise TypeError, 'wrong number of arguments' 16353105Sstever@eecs.umich.edu 16363109Sstever@eecs.umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 16373109Sstever@eecs.umich.edu# proxy objects (via set_param_desc()) so that proxy error messages 16383109Sstever@eecs.umich.edu# make sense. 16393109Sstever@eecs.umich.educlass PortParamDesc(object): 16403109Sstever@eecs.umich.edu __metaclass__ = Singleton 16413109Sstever@eecs.umich.edu 16423109Sstever@eecs.umich.edu ptype_str = 'Port' 16433109Sstever@eecs.umich.edu ptype = Port 16443105Sstever@eecs.umich.edu 16456654Snate@binkert.orgbaseEnums = allEnums.copy() 16466654Snate@binkert.orgbaseParams = allParams.copy() 16476654Snate@binkert.org 16486654Snate@binkert.orgdef clear(): 16496654Snate@binkert.org global allEnums, allParams 16506654Snate@binkert.org 16516654Snate@binkert.org allEnums = baseEnums.copy() 16526654Snate@binkert.org allParams = baseParams.copy() 16536654Snate@binkert.org 16543101Sstever@eecs.umich.edu__all__ = ['Param', 'VectorParam', 16553101Sstever@eecs.umich.edu 'Enum', 'Bool', 'String', 'Float', 16563101Sstever@eecs.umich.edu 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 16573101Sstever@eecs.umich.edu 'Int32', 'UInt32', 'Int64', 'UInt64', 16583101Sstever@eecs.umich.edu 'Counter', 'Addr', 'Tick', 'Percent', 16593101Sstever@eecs.umich.edu 'TcpPort', 'UdpPort', 'EthernetAddr', 16607777Sgblack@eecs.umich.edu 'IpAddress', 'IpNetmask', 'IpWithPort', 16613101Sstever@eecs.umich.edu 'MemorySize', 'MemorySize32', 16629827Sakash.bagdia@arm.com 'Latency', 'Frequency', 'Clock', 'Voltage', 16633101Sstever@eecs.umich.edu 'NetworkBandwidth', 'MemoryBandwidth', 16649232Sandreas.hansson@arm.com 'AddrRange', 16653101Sstever@eecs.umich.edu 'MaxAddr', 'MaxTick', 'AllMemory', 16663885Sbinkertn@umich.edu 'Time', 16673102Sstever@eecs.umich.edu 'NextEthernetAddr', 'NULL', 16688839Sandreas.hansson@arm.com 'MasterPort', 'SlavePort', 16698839Sandreas.hansson@arm.com 'VectorMasterPort', 'VectorSlavePort'] 16706654Snate@binkert.org 16716654Snate@binkert.orgimport SimObject 1672