params.py revision 13542:5e914b841659
18839Sandreas.hansson@arm.com# Copyright (c) 2012-2014, 2017 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.edufrom __future__ import print_function 633885Sbinkertn@umich.edu 644762Snate@binkert.orgimport copy 653885Sbinkertn@umich.eduimport datetime 663885Sbinkertn@umich.eduimport re 677528Ssteve.reinhardt@amd.comimport sys 683885Sbinkertn@umich.eduimport time 694380Sbinkertn@umich.eduimport math 704167Sbinkertn@umich.edu 713102Sstever@eecs.umich.eduimport proxy 723101Sstever@eecs.umich.eduimport ticks 734762Snate@binkert.orgfrom util import * 744762Snate@binkert.org 754762Snate@binkert.orgdef isSimObject(*args, **kwargs): 764762Snate@binkert.org return SimObject.isSimObject(*args, **kwargs) 774762Snate@binkert.org 784762Snate@binkert.orgdef isSimObjectSequence(*args, **kwargs): 794762Snate@binkert.org return SimObject.isSimObjectSequence(*args, **kwargs) 804762Snate@binkert.org 814762Snate@binkert.orgdef isSimObjectClass(*args, **kwargs): 825033Smilesck@eecs.umich.edu return SimObject.isSimObjectClass(*args, **kwargs) 835033Smilesck@eecs.umich.edu 845033Smilesck@eecs.umich.eduallParams = {} 855033Smilesck@eecs.umich.edu 865033Smilesck@eecs.umich.educlass MetaParamValue(type): 875033Smilesck@eecs.umich.edu def __new__(mcls, name, bases, dct): 885033Smilesck@eecs.umich.edu cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) 895033Smilesck@eecs.umich.edu assert name not in allParams 905033Smilesck@eecs.umich.edu allParams[name] = cls 915033Smilesck@eecs.umich.edu return cls 923101Sstever@eecs.umich.edu 933101Sstever@eecs.umich.edu 943101Sstever@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject 955033Smilesck@eecs.umich.edu# parameters. 963101Sstever@eecs.umich.educlass ParamValue(object): 978596Ssteve.reinhardt@amd.com __metaclass__ = MetaParamValue 988596Ssteve.reinhardt@amd.com cmd_line_settable = False 998596Ssteve.reinhardt@amd.com 1008596Ssteve.reinhardt@amd.com # Generate the code needed as a prerequisite for declaring a C++ 1017673Snate@binkert.org # object of this type. Typically generates one or more #include 1027673Snate@binkert.org # statements. Used when declaring parameters of this type. 1037673Snate@binkert.org @classmethod 1047673Snate@binkert.org def cxx_predecls(cls, code): 1058596Ssteve.reinhardt@amd.com pass 1068596Ssteve.reinhardt@amd.com 1078596Ssteve.reinhardt@amd.com @classmethod 1087673Snate@binkert.org def pybind_predecls(cls, code): 1097673Snate@binkert.org cls.cxx_predecls(code) 1107673Snate@binkert.org 1113101Sstever@eecs.umich.edu # default for printing to .ini file is regular string conversion. 1123101Sstever@eecs.umich.edu # will be overridden in some cases 1133101Sstever@eecs.umich.edu def ini_str(self): 1143101Sstever@eecs.umich.edu return str(self) 1153101Sstever@eecs.umich.edu 1163101Sstever@eecs.umich.edu # default for printing to .json file is regular string conversion. 1173101Sstever@eecs.umich.edu # will be overridden in some cases, mostly to use native Python 1183101Sstever@eecs.umich.edu # types where there are similar JSON types 1193101Sstever@eecs.umich.edu def config_value(self): 1203101Sstever@eecs.umich.edu return str(self) 1213101Sstever@eecs.umich.edu 1223101Sstever@eecs.umich.edu # Prerequisites for .ini parsing with cxx_ini_parse 1233101Sstever@eecs.umich.edu @classmethod 1243101Sstever@eecs.umich.edu def cxx_ini_predecls(cls, code): 1253101Sstever@eecs.umich.edu pass 1263101Sstever@eecs.umich.edu 1273101Sstever@eecs.umich.edu # parse a .ini file entry for this param from string expression 1283101Sstever@eecs.umich.edu # src into lvalue dest (of the param's C++ type) 1293101Sstever@eecs.umich.edu @classmethod 1303101Sstever@eecs.umich.edu def cxx_ini_parse(cls, code, src, dest, ret): 1313101Sstever@eecs.umich.edu code('// Unhandled param type: %s' % cls.__name__) 1323101Sstever@eecs.umich.edu code('%s false;' % ret) 1333101Sstever@eecs.umich.edu 1343101Sstever@eecs.umich.edu # allows us to blithely call unproxy() on things without checking 1353101Sstever@eecs.umich.edu # if they're really proxies or not 1363101Sstever@eecs.umich.edu def unproxy(self, base): 1373101Sstever@eecs.umich.edu return self 1383101Sstever@eecs.umich.edu 1393101Sstever@eecs.umich.edu # Produce a human readable version of the stored value 1403101Sstever@eecs.umich.edu def pretty_print(self, value): 1413101Sstever@eecs.umich.edu return str(value) 1423101Sstever@eecs.umich.edu 1433101Sstever@eecs.umich.edu# Regular parameter description. 1443101Sstever@eecs.umich.educlass ParamDesc(object): 1453101Sstever@eecs.umich.edu def __init__(self, ptype_str, ptype, *args, **kwargs): 1463101Sstever@eecs.umich.edu self.ptype_str = ptype_str 1473101Sstever@eecs.umich.edu # remember ptype only if it is provided 1483101Sstever@eecs.umich.edu if ptype != None: 1493101Sstever@eecs.umich.edu self.ptype = ptype 1503101Sstever@eecs.umich.edu 1513101Sstever@eecs.umich.edu if args: 1523101Sstever@eecs.umich.edu if len(args) == 1: 1533101Sstever@eecs.umich.edu self.desc = args[0] 1543101Sstever@eecs.umich.edu elif len(args) == 2: 1553101Sstever@eecs.umich.edu self.default = args[0] 1563101Sstever@eecs.umich.edu self.desc = args[1] 1575033Smilesck@eecs.umich.edu else: 1586656Snate@binkert.org raise TypeError, 'too many arguments' 1595033Smilesck@eecs.umich.edu 1605033Smilesck@eecs.umich.edu if kwargs.has_key('desc'): 1615033Smilesck@eecs.umich.edu assert(not hasattr(self, 'desc')) 1623101Sstever@eecs.umich.edu self.desc = kwargs['desc'] 1633101Sstever@eecs.umich.edu del kwargs['desc'] 1643101Sstever@eecs.umich.edu 1653101Sstever@eecs.umich.edu if kwargs.has_key('default'): 1663101Sstever@eecs.umich.edu assert(not hasattr(self, 'default')) 1673101Sstever@eecs.umich.edu self.default = kwargs['default'] 1683101Sstever@eecs.umich.edu del kwargs['default'] 1693101Sstever@eecs.umich.edu 1703101Sstever@eecs.umich.edu if kwargs: 1713101Sstever@eecs.umich.edu raise TypeError, 'extra unknown kwargs %s' % kwargs 1723101Sstever@eecs.umich.edu 1733101Sstever@eecs.umich.edu if not hasattr(self, 'desc'): 1743101Sstever@eecs.umich.edu raise TypeError, 'desc attribute missing' 1753102Sstever@eecs.umich.edu 1763101Sstever@eecs.umich.edu def __getattr__(self, attr): 1773101Sstever@eecs.umich.edu if attr == 'ptype': 1783101Sstever@eecs.umich.edu ptype = SimObject.allClasses[self.ptype_str] 1797673Snate@binkert.org assert isSimObjectClass(ptype) 1808607Sgblack@eecs.umich.edu self.ptype = ptype 1817673Snate@binkert.org return ptype 1823101Sstever@eecs.umich.edu 1837673Snate@binkert.org raise AttributeError, "'%s' object has no attribute '%s'" % \ 1847673Snate@binkert.org (type(self).__name__, attr) 1853101Sstever@eecs.umich.edu 1867673Snate@binkert.org def example_str(self): 1877673Snate@binkert.org if hasattr(self.ptype, "ex_str"): 1883101Sstever@eecs.umich.edu return self.ptype.ex_str 1893101Sstever@eecs.umich.edu else: 1903101Sstever@eecs.umich.edu return self.ptype_str 1913101Sstever@eecs.umich.edu 1923101Sstever@eecs.umich.edu # Is the param available to be exposed on the command line 1933101Sstever@eecs.umich.edu def isCmdLineSettable(self): 1945033Smilesck@eecs.umich.edu if hasattr(self.ptype, "cmd_line_settable"): 1955475Snate@binkert.org return self.ptype.cmd_line_settable 1965475Snate@binkert.org else: 1975475Snate@binkert.org return False 1985475Snate@binkert.org 1993101Sstever@eecs.umich.edu def convert(self, value): 2003101Sstever@eecs.umich.edu if isinstance(value, proxy.BaseProxy): 2013101Sstever@eecs.umich.edu value.set_param_desc(self) 2024762Snate@binkert.org return value 2034762Snate@binkert.org if not hasattr(self, 'ptype') and isNullPointer(value): 2044762Snate@binkert.org # deferred evaluation of SimObject; continue to defer if 2053101Sstever@eecs.umich.edu # we're just assigning a null pointer 2068460SAli.Saidi@ARM.com return value 2078459SAli.Saidi@ARM.com if isinstance(value, self.ptype): 2088459SAli.Saidi@ARM.com return value 2098459SAli.Saidi@ARM.com if isNullPointer(value) and isSimObjectClass(self.ptype): 2103101Sstever@eecs.umich.edu return value 2117528Ssteve.reinhardt@amd.com return self.ptype(value) 2127528Ssteve.reinhardt@amd.com 2137528Ssteve.reinhardt@amd.com def pretty_print(self, value): 2147528Ssteve.reinhardt@amd.com if isinstance(value, proxy.BaseProxy): 2157528Ssteve.reinhardt@amd.com return str(value) 2167528Ssteve.reinhardt@amd.com if isNullPointer(value): 2173101Sstever@eecs.umich.edu return NULL 2187528Ssteve.reinhardt@amd.com return self.ptype(value).pretty_print(value) 2197528Ssteve.reinhardt@amd.com 2207528Ssteve.reinhardt@amd.com def cxx_predecls(self, code): 2217528Ssteve.reinhardt@amd.com code('#include <cstddef>') 2227528Ssteve.reinhardt@amd.com self.ptype.cxx_predecls(code) 2237528Ssteve.reinhardt@amd.com 2247528Ssteve.reinhardt@amd.com def pybind_predecls(self, code): 2257528Ssteve.reinhardt@amd.com self.ptype.pybind_predecls(code) 2267528Ssteve.reinhardt@amd.com 2277528Ssteve.reinhardt@amd.com def cxx_decl(self, code): 2288321Ssteve.reinhardt@amd.com code('${{self.ptype.cxx_type}} ${{self.name}};') 2298321Ssteve.reinhardt@amd.com 2307528Ssteve.reinhardt@amd.com# Vector-valued parameter description. Just like ParamDesc, except 2317528Ssteve.reinhardt@amd.com# that the value is a vector (list) of the specified type instead of a 2327528Ssteve.reinhardt@amd.com# single value. 2337528Ssteve.reinhardt@amd.com 2347528Ssteve.reinhardt@amd.comclass VectorParamValue(list): 2357528Ssteve.reinhardt@amd.com __metaclass__ = MetaParamValue 2367528Ssteve.reinhardt@amd.com def __setattr__(self, attr, value): 2377528Ssteve.reinhardt@amd.com raise AttributeError, \ 2387528Ssteve.reinhardt@amd.com "Not allowed to set %s on '%s'" % (attr, type(self).__name__) 2397528Ssteve.reinhardt@amd.com 2407528Ssteve.reinhardt@amd.com def config_value(self): 2417528Ssteve.reinhardt@amd.com return [v.config_value() for v in self] 2427528Ssteve.reinhardt@amd.com 2433101Sstever@eecs.umich.edu def ini_str(self): 2448664SAli.Saidi@ARM.com return ' '.join([v.ini_str() for v in self]) 2458664SAli.Saidi@ARM.com 2468664SAli.Saidi@ARM.com def getValue(self): 2478664SAli.Saidi@ARM.com return [ v.getValue() for v in self ] 2488664SAli.Saidi@ARM.com 2498664SAli.Saidi@ARM.com def unproxy(self, base): 2503101Sstever@eecs.umich.edu if len(self) == 1 and isinstance(self[0], proxy.BaseProxy): 2513101Sstever@eecs.umich.edu # The value is a proxy (e.g. Parent.any, Parent.all or 2523101Sstever@eecs.umich.edu # Parent.x) therefore try resolve it 2533101Sstever@eecs.umich.edu return self[0].unproxy(base) 2543101Sstever@eecs.umich.edu else: 2553101Sstever@eecs.umich.edu return [v.unproxy(base) for v in self] 2563101Sstever@eecs.umich.edu 2573101Sstever@eecs.umich.educlass SimObjectVector(VectorParamValue): 2584762Snate@binkert.org # support clone operation 2594762Snate@binkert.org def __call__(self, **kwargs): 2604762Snate@binkert.org return SimObjectVector([v(**kwargs) for v in self]) 2614762Snate@binkert.org 2627528Ssteve.reinhardt@amd.com def clear_parent(self, old_parent): 2634762Snate@binkert.org for v in self: 2644762Snate@binkert.org v.clear_parent(old_parent) 2654762Snate@binkert.org 2668596Ssteve.reinhardt@amd.com def set_parent(self, parent, name): 2678596Ssteve.reinhardt@amd.com if len(self) == 1: 2688596Ssteve.reinhardt@amd.com self[0].set_parent(parent, name) 2697673Snate@binkert.org else: 2708596Ssteve.reinhardt@amd.com width = int(math.ceil(math.log(len(self))/math.log(10))) 2714762Snate@binkert.org for i,v in enumerate(self): 2727673Snate@binkert.org v.set_parent(parent, "%s%0*d" % (name, width, i)) 2738596Ssteve.reinhardt@amd.com 2747675Snate@binkert.org def has_parent(self): 2757675Snate@binkert.org return any([e.has_parent() for e in self if not isNullPointer(e)]) 2767675Snate@binkert.org 2777675Snate@binkert.org # return 'cpu0 cpu1' etc. for print_ini() 2788656Sandreas.hansson@arm.com def get_name(self): 2798656Sandreas.hansson@arm.com return ' '.join([v._name for v in self]) 2808656Sandreas.hansson@arm.com 2817675Snate@binkert.org # By iterating through the constituent members of the vector here 2827675Snate@binkert.org # we can nicely handle iterating over all a SimObject's children 2837673Snate@binkert.org # without having to provide lots of special functions on 2847675Snate@binkert.org # SimObjectVector directly. 2857675Snate@binkert.org def descendants(self): 2867675Snate@binkert.org for v in self: 2877675Snate@binkert.org for obj in v.descendants(): 2887675Snate@binkert.org yield obj 2897673Snate@binkert.org 2907675Snate@binkert.org def get_config_as_dict(self): 2917675Snate@binkert.org a = [] 2927675Snate@binkert.org for v in self: 2937675Snate@binkert.org a.append(v.get_config_as_dict()) 2947675Snate@binkert.org return a 2957675Snate@binkert.org 2967675Snate@binkert.org # If we are replacing an item in the vector, make sure to set the 2977675Snate@binkert.org # parent reference of the new SimObject to be the same as the parent 2987675Snate@binkert.org # of the SimObject being replaced. Useful to have if we created 2997675Snate@binkert.org # a SimObjectVector of temporary objects that will be modified later in 3007675Snate@binkert.org # configuration scripts. 3017675Snate@binkert.org def __setitem__(self, key, value): 3027675Snate@binkert.org val = self[key] 3037675Snate@binkert.org if value.has_parent(): 3047675Snate@binkert.org warn("SimObject %s already has a parent" % value.get_name() +\ 3057675Snate@binkert.org " that is being overwritten by a SimObjectVector") 3067673Snate@binkert.org value.set_parent(val.get_parent(), val._name) 3077673Snate@binkert.org super(SimObjectVector, self).__setitem__(key, value) 3083101Sstever@eecs.umich.edu 3097675Snate@binkert.org # Enumerate the params of each member of the SimObject vector. Creates 3107675Snate@binkert.org # strings that will allow indexing into the vector by the python code and 3117673Snate@binkert.org # allow it to be specified on the command line. 3127673Snate@binkert.org def enumerateParams(self, flags_dict = {}, 3137673Snate@binkert.org cmd_line_str = "", 3143101Sstever@eecs.umich.edu access_str = ""): 3157673Snate@binkert.org if hasattr(self, "_paramEnumed"): 3167673Snate@binkert.org print("Cycle detected enumerating params at %s?!" % (cmd_line_str)) 3173101Sstever@eecs.umich.edu else: 3183101Sstever@eecs.umich.edu x = 0 3193101Sstever@eecs.umich.edu for vals in self: 3203101Sstever@eecs.umich.edu # Each entry in the SimObjectVector should be an 3213101Sstever@eecs.umich.edu # instance of a SimObject 3223101Sstever@eecs.umich.edu flags_dict = vals.enumerateParams(flags_dict, 3233101Sstever@eecs.umich.edu cmd_line_str + "%d." % x, 3243101Sstever@eecs.umich.edu access_str + "[%d]." % x) 3253101Sstever@eecs.umich.edu x = x + 1 3263101Sstever@eecs.umich.edu 3273101Sstever@eecs.umich.edu return flags_dict 3283101Sstever@eecs.umich.edu 3293101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc): 3303101Sstever@eecs.umich.edu # Convert assigned value to appropriate type. If the RHS is not a 3313101Sstever@eecs.umich.edu # list or tuple, it generates a single-element list. 3325033Smilesck@eecs.umich.edu def convert(self, value): 3335033Smilesck@eecs.umich.edu if isinstance(value, (list, tuple)): 3343101Sstever@eecs.umich.edu # list: coerce each element into new list 3353101Sstever@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) for v in value ] 3363101Sstever@eecs.umich.edu elif isinstance(value, str): 3373101Sstever@eecs.umich.edu # If input is a csv string 3383101Sstever@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) \ 3393101Sstever@eecs.umich.edu for v in value.strip('[').strip(']').split(',') ] 3403101Sstever@eecs.umich.edu else: 3413101Sstever@eecs.umich.edu # singleton: coerce to a single-element list 3423101Sstever@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, value) ] 3433101Sstever@eecs.umich.edu 3443101Sstever@eecs.umich.edu if isSimObjectSequence(tmp_list): 3453101Sstever@eecs.umich.edu return SimObjectVector(tmp_list) 3463101Sstever@eecs.umich.edu else: 3473101Sstever@eecs.umich.edu return VectorParamValue(tmp_list) 3483101Sstever@eecs.umich.edu 3493101Sstever@eecs.umich.edu # Produce a human readable example string that describes 3503101Sstever@eecs.umich.edu # how to set this vector parameter in the absence of a default 3513101Sstever@eecs.umich.edu # value. 3523101Sstever@eecs.umich.edu def example_str(self): 3533101Sstever@eecs.umich.edu s = super(VectorParamDesc, self).example_str() 3543101Sstever@eecs.umich.edu help_str = "[" + s + "," + s + ", ...]" 3553101Sstever@eecs.umich.edu return help_str 3563101Sstever@eecs.umich.edu 3573101Sstever@eecs.umich.edu # Produce a human readable representation of the value of this vector param. 3583101Sstever@eecs.umich.edu def pretty_print(self, value): 3597673Snate@binkert.org if isinstance(value, (list, tuple)): 3607673Snate@binkert.org tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ] 3617673Snate@binkert.org elif isinstance(value, str): 3627673Snate@binkert.org tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ] 3637673Snate@binkert.org else: 3647673Snate@binkert.org tmp_list = [ ParamDesc.pretty_print(self, value) ] 3657673Snate@binkert.org 3667673Snate@binkert.org return tmp_list 3674762Snate@binkert.org 3684762Snate@binkert.org # This is a helper function for the new config system 3694762Snate@binkert.org def __call__(self, value): 3703101Sstever@eecs.umich.edu if isinstance(value, (list, tuple)): 3713101Sstever@eecs.umich.edu # list: coerce each element into new list 3723101Sstever@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) for v in value ] 3733101Sstever@eecs.umich.edu elif isinstance(value, str): 3743101Sstever@eecs.umich.edu # If input is a csv string 3753101Sstever@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) \ 3763101Sstever@eecs.umich.edu for v in value.strip('[').strip(']').split(',') ] 3773101Sstever@eecs.umich.edu else: 3783101Sstever@eecs.umich.edu # singleton: coerce to a single-element list 3793101Sstever@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, value) ] 3803101Sstever@eecs.umich.edu 3813714Sstever@eecs.umich.edu return VectorParamValue(tmp_list) 3823714Sstever@eecs.umich.edu 3833714Sstever@eecs.umich.edu def cxx_predecls(self, code): 3843714Sstever@eecs.umich.edu code('#include <vector>') 3853714Sstever@eecs.umich.edu self.ptype.cxx_predecls(code) 3863714Sstever@eecs.umich.edu 3873101Sstever@eecs.umich.edu def pybind_predecls(self, code): 3883101Sstever@eecs.umich.edu code('#include <vector>') 3893101Sstever@eecs.umich.edu self.ptype.pybind_predecls(code) 3903101Sstever@eecs.umich.edu 3913101Sstever@eecs.umich.edu def cxx_decl(self, code): 3923101Sstever@eecs.umich.edu code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};') 3933101Sstever@eecs.umich.edu 3943101Sstever@eecs.umich.educlass ParamFactory(object): 3953101Sstever@eecs.umich.edu def __init__(self, param_desc_class, ptype_str = None): 3963101Sstever@eecs.umich.edu self.param_desc_class = param_desc_class 3973101Sstever@eecs.umich.edu self.ptype_str = ptype_str 3983101Sstever@eecs.umich.edu 3993101Sstever@eecs.umich.edu def __getattr__(self, attr): 4003101Sstever@eecs.umich.edu if self.ptype_str: 4013101Sstever@eecs.umich.edu attr = self.ptype_str + '.' + attr 4023101Sstever@eecs.umich.edu return ParamFactory(self.param_desc_class, attr) 4033101Sstever@eecs.umich.edu 4043101Sstever@eecs.umich.edu # E.g., Param.Int(5, "number of widgets") 4053101Sstever@eecs.umich.edu def __call__(self, *args, **kwargs): 4063101Sstever@eecs.umich.edu ptype = None 4073101Sstever@eecs.umich.edu try: 4083101Sstever@eecs.umich.edu ptype = allParams[self.ptype_str] 4093101Sstever@eecs.umich.edu except KeyError: 4103101Sstever@eecs.umich.edu # if name isn't defined yet, assume it's a SimObject, and 4113101Sstever@eecs.umich.edu # try to resolve it later 4125033Smilesck@eecs.umich.edu pass 4133101Sstever@eecs.umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 4143101Sstever@eecs.umich.edu 4153101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc) 4163101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc) 4173101Sstever@eecs.umich.edu 4183101Sstever@eecs.umich.edu##################################################################### 4193101Sstever@eecs.umich.edu# 4203101Sstever@eecs.umich.edu# Parameter Types 4213101Sstever@eecs.umich.edu# 4223101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types 4233101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more 4243101Sstever@eecs.umich.edu# flexible to define our own set of types. This gives us more control 4255822Ssaidi@eecs.umich.edu# over how Python expressions are converted to values (via the 4265822Ssaidi@eecs.umich.edu# __init__() constructor) and how these values are printed out (via 4273101Sstever@eecs.umich.edu# the __str__() conversion method). 4283101Sstever@eecs.umich.edu# 4293101Sstever@eecs.umich.edu##################################################################### 4303101Sstever@eecs.umich.edu 4313101Sstever@eecs.umich.edu# String-valued parameter. Just mixin the ParamValue class with the 4323101Sstever@eecs.umich.edu# built-in str class. 4333101Sstever@eecs.umich.educlass String(ParamValue,str): 4343101Sstever@eecs.umich.edu cxx_type = 'std::string' 4353101Sstever@eecs.umich.edu cmd_line_settable = True 4363101Sstever@eecs.umich.edu 4373101Sstever@eecs.umich.edu @classmethod 4383101Sstever@eecs.umich.edu def cxx_predecls(self, code): 4393101Sstever@eecs.umich.edu code('#include <string>') 4403101Sstever@eecs.umich.edu 4413101Sstever@eecs.umich.edu def __call__(self, value): 4423101Sstever@eecs.umich.edu self = value 4433101Sstever@eecs.umich.edu return value 4443101Sstever@eecs.umich.edu 4453101Sstever@eecs.umich.edu @classmethod 4463101Sstever@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 4473101Sstever@eecs.umich.edu code('%s = %s;' % (dest, src)) 4483102Sstever@eecs.umich.edu code('%s true;' % ret) 4493714Sstever@eecs.umich.edu 4503101Sstever@eecs.umich.edu def getValue(self): 4513714Sstever@eecs.umich.edu return self 4523714Sstever@eecs.umich.edu 4533714Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math 4543101Sstever@eecs.umich.edu# operations in a type-safe way. e.g., a Latency times an int returns 4553101Sstever@eecs.umich.edu# a new Latency object. 4567673Snate@binkert.orgclass NumericParamValue(ParamValue): 4577673Snate@binkert.org def __str__(self): 4587673Snate@binkert.org return str(self.value) 4597673Snate@binkert.org 4607673Snate@binkert.org def __float__(self): 4617673Snate@binkert.org return float(self.value) 4627673Snate@binkert.org 4637673Snate@binkert.org def __long__(self): 4647673Snate@binkert.org return long(self.value) 4657673Snate@binkert.org 4667673Snate@binkert.org def __int__(self): 4674762Snate@binkert.org return int(self.value) 4684762Snate@binkert.org 4694762Snate@binkert.org # hook for bounds checking 4703101Sstever@eecs.umich.edu def _check(self): 4713101Sstever@eecs.umich.edu return 4723101Sstever@eecs.umich.edu 4733101Sstever@eecs.umich.edu def __mul__(self, other): 4743101Sstever@eecs.umich.edu newobj = self.__class__(self) 4753101Sstever@eecs.umich.edu newobj.value *= other 4763101Sstever@eecs.umich.edu newobj._check() 4773101Sstever@eecs.umich.edu return newobj 4783101Sstever@eecs.umich.edu 4793101Sstever@eecs.umich.edu __rmul__ = __mul__ 4803101Sstever@eecs.umich.edu 4813101Sstever@eecs.umich.edu def __div__(self, other): 4823101Sstever@eecs.umich.edu newobj = self.__class__(self) 4833101Sstever@eecs.umich.edu newobj.value /= other 4843101Sstever@eecs.umich.edu newobj._check() 4853101Sstever@eecs.umich.edu return newobj 4863101Sstever@eecs.umich.edu 4873101Sstever@eecs.umich.edu def __sub__(self, other): 4883101Sstever@eecs.umich.edu newobj = self.__class__(self) 4893101Sstever@eecs.umich.edu newobj.value -= other 4904446Sbinkertn@umich.edu newobj._check() 4913101Sstever@eecs.umich.edu return newobj 4925468Snate@binkert.org 4935468Snate@binkert.org def config_value(self): 4945468Snate@binkert.org return self.value 4955468Snate@binkert.org 4965468Snate@binkert.org @classmethod 4975468Snate@binkert.org def cxx_ini_predecls(cls, code): 4985468Snate@binkert.org # Assume that base/str.hh will be included anyway 4994762Snate@binkert.org # code('#include "base/str.hh"') 5004762Snate@binkert.org pass 5014762Snate@binkert.org 5023101Sstever@eecs.umich.edu # The default for parsing PODs from an .ini entry is to extract from an 5033101Sstever@eecs.umich.edu # istringstream and let overloading choose the right type according to 5043101Sstever@eecs.umich.edu # the dest type. 5053101Sstever@eecs.umich.edu @classmethod 5063101Sstever@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 5073101Sstever@eecs.umich.edu code('%s to_number(%s, %s);' % (ret, src, dest)) 5083101Sstever@eecs.umich.edu 5093101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters. See CheckedInt. 5103102Sstever@eecs.umich.educlass CheckedIntType(MetaParamValue): 5113101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 5123101Sstever@eecs.umich.edu super(CheckedIntType, cls).__init__(name, bases, dict) 5133101Sstever@eecs.umich.edu 5144168Sbinkertn@umich.edu # CheckedInt is an abstract base class, so we actually don't 5153101Sstever@eecs.umich.edu # want to do any processing on it... the rest of this code is 5163101Sstever@eecs.umich.edu # just for classes that derive from CheckedInt. 5173101Sstever@eecs.umich.edu if name == 'CheckedInt': 5183101Sstever@eecs.umich.edu return 5193101Sstever@eecs.umich.edu 5203101Sstever@eecs.umich.edu if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 5213102Sstever@eecs.umich.edu if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 5223101Sstever@eecs.umich.edu panic("CheckedInt subclass %s must define either\n" \ 5233101Sstever@eecs.umich.edu " 'min' and 'max' or 'size' and 'unsigned'\n", 5243101Sstever@eecs.umich.edu name); 5253101Sstever@eecs.umich.edu if cls.unsigned: 5263101Sstever@eecs.umich.edu cls.min = 0 5273101Sstever@eecs.umich.edu cls.max = 2 ** cls.size - 1 5283101Sstever@eecs.umich.edu else: 5293101Sstever@eecs.umich.edu cls.min = -(2 ** (cls.size - 1)) 5303101Sstever@eecs.umich.edu cls.max = (2 ** (cls.size - 1)) - 1 5313101Sstever@eecs.umich.edu 5323101Sstever@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters. This 5333102Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific 5343101Sstever@eecs.umich.edu# bounds. Initialization of the min and max bounds is done in the 5353101Sstever@eecs.umich.edu# metaclass CheckedIntType.__init__. 5363101Sstever@eecs.umich.educlass CheckedInt(NumericParamValue): 5373584Ssaidi@eecs.umich.edu __metaclass__ = CheckedIntType 5383584Ssaidi@eecs.umich.edu cmd_line_settable = True 5393584Ssaidi@eecs.umich.edu 5403584Ssaidi@eecs.umich.edu def _check(self): 5413584Ssaidi@eecs.umich.edu if not self.min <= self.value <= self.max: 5423101Sstever@eecs.umich.edu raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 5433101Sstever@eecs.umich.edu (self.min, self.value, self.max) 5445033Smilesck@eecs.umich.edu 5453101Sstever@eecs.umich.edu def __init__(self, value): 5463101Sstever@eecs.umich.edu if isinstance(value, str): 5473101Sstever@eecs.umich.edu self.value = convert.toInteger(value) 5483101Sstever@eecs.umich.edu elif isinstance(value, (int, long, float, NumericParamValue)): 5493101Sstever@eecs.umich.edu self.value = long(value) 5503101Sstever@eecs.umich.edu else: 5513101Sstever@eecs.umich.edu raise TypeError, "Can't convert object of type %s to CheckedInt" \ 5523101Sstever@eecs.umich.edu % type(value).__name__ 5533101Sstever@eecs.umich.edu self._check() 5543101Sstever@eecs.umich.edu 5553101Sstever@eecs.umich.edu def __call__(self, value): 5563101Sstever@eecs.umich.edu self.__init__(value) 5573101Sstever@eecs.umich.edu return value 5583101Sstever@eecs.umich.edu 5593101Sstever@eecs.umich.edu @classmethod 5603101Sstever@eecs.umich.edu def cxx_predecls(cls, code): 5613101Sstever@eecs.umich.edu # most derived types require this, so we just do it here once 5623101Sstever@eecs.umich.edu code('#include "base/types.hh"') 5633101Sstever@eecs.umich.edu 5643101Sstever@eecs.umich.edu def getValue(self): 5653101Sstever@eecs.umich.edu return long(self.value) 5663101Sstever@eecs.umich.edu 5673101Sstever@eecs.umich.educlass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 5683101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 5693101Sstever@eecs.umich.edu 5703101Sstever@eecs.umich.educlass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 5713101Sstever@eecs.umich.educlass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 5723101Sstever@eecs.umich.educlass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 5733101Sstever@eecs.umich.educlass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 5745219Ssaidi@eecs.umich.educlass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 5755219Ssaidi@eecs.umich.educlass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 5765219Ssaidi@eecs.umich.educlass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 5773101Sstever@eecs.umich.educlass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 5783101Sstever@eecs.umich.edu 5793101Sstever@eecs.umich.educlass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 5803101Sstever@eecs.umich.educlass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 5813101Sstever@eecs.umich.educlass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 5823101Sstever@eecs.umich.educlass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 5833101Sstever@eecs.umich.edu 5843101Sstever@eecs.umich.educlass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 5853101Sstever@eecs.umich.edu 5863101Sstever@eecs.umich.educlass Cycles(CheckedInt): 5873101Sstever@eecs.umich.edu cxx_type = 'Cycles' 5883101Sstever@eecs.umich.edu size = 64 5893101Sstever@eecs.umich.edu unsigned = True 5903101Sstever@eecs.umich.edu 5913101Sstever@eecs.umich.edu def getValue(self): 5923101Sstever@eecs.umich.edu from _m5.core import Cycles 5937673Snate@binkert.org return Cycles(self.value) 5947673Snate@binkert.org 5957675Snate@binkert.org @classmethod 5967673Snate@binkert.org def cxx_ini_predecls(cls, code): 5977675Snate@binkert.org # Assume that base/str.hh will be included anyway 5987675Snate@binkert.org # code('#include "base/str.hh"') 5997675Snate@binkert.org pass 6007675Snate@binkert.org 6017675Snate@binkert.org @classmethod 6027673Snate@binkert.org def cxx_ini_parse(cls, code, src, dest, ret): 6033101Sstever@eecs.umich.edu code('uint64_t _temp;') 6043101Sstever@eecs.umich.edu code('bool _ret = to_number(%s, _temp);' % src) 6057673Snate@binkert.org code('if (_ret)') 6064762Snate@binkert.org code(' %s = Cycles(_temp);' % dest) 6077675Snate@binkert.org code('%s _ret;' % ret) 6084762Snate@binkert.org 6094762Snate@binkert.orgclass Float(ParamValue, float): 6104762Snate@binkert.org cxx_type = 'double' 6114762Snate@binkert.org cmd_line_settable = True 6124762Snate@binkert.org 6133101Sstever@eecs.umich.edu def __init__(self, value): 6143101Sstever@eecs.umich.edu if isinstance(value, (int, long, float, NumericParamValue, Float, str)): 6153101Sstever@eecs.umich.edu self.value = float(value) 6167673Snate@binkert.org else: 6174762Snate@binkert.org raise TypeError, "Can't convert object of type %s to Float" \ 6187675Snate@binkert.org % type(value).__name__ 6194762Snate@binkert.org 6204762Snate@binkert.org def __call__(self, value): 6214762Snate@binkert.org self.__init__(value) 6224762Snate@binkert.org return value 6234762Snate@binkert.org 6243101Sstever@eecs.umich.edu def getValue(self): 6253101Sstever@eecs.umich.edu return float(self.value) 6263101Sstever@eecs.umich.edu 6273101Sstever@eecs.umich.edu def config_value(self): 6283101Sstever@eecs.umich.edu return self 6293101Sstever@eecs.umich.edu 6303101Sstever@eecs.umich.edu @classmethod 6313101Sstever@eecs.umich.edu def cxx_ini_predecls(cls, code): 6323102Sstever@eecs.umich.edu code('#include <sstream>') 6333101Sstever@eecs.umich.edu 6343101Sstever@eecs.umich.edu @classmethod 6353101Sstever@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 6364762Snate@binkert.org code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 6374762Snate@binkert.org 6384762Snate@binkert.orgclass MemorySize(CheckedInt): 6393101Sstever@eecs.umich.edu cxx_type = 'uint64_t' 6403101Sstever@eecs.umich.edu ex_str = '512MB' 6413101Sstever@eecs.umich.edu size = 64 6423101Sstever@eecs.umich.edu unsigned = True 6433101Sstever@eecs.umich.edu def __init__(self, value): 6443101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 6453101Sstever@eecs.umich.edu self.value = value.value 6463101Sstever@eecs.umich.edu else: 6473101Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 6483101Sstever@eecs.umich.edu self._check() 6493101Sstever@eecs.umich.edu 6503101Sstever@eecs.umich.educlass MemorySize32(CheckedInt): 6513101Sstever@eecs.umich.edu cxx_type = 'uint32_t' 6523101Sstever@eecs.umich.edu ex_str = '512MB' 6533101Sstever@eecs.umich.edu size = 32 6543101Sstever@eecs.umich.edu unsigned = True 6553101Sstever@eecs.umich.edu def __init__(self, value): 6563101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 6573101Sstever@eecs.umich.edu self.value = value.value 6583101Sstever@eecs.umich.edu else: 6594380Sbinkertn@umich.edu self.value = convert.toMemorySize(value) 6604380Sbinkertn@umich.edu self._check() 6614380Sbinkertn@umich.edu 6623101Sstever@eecs.umich.educlass Addr(CheckedInt): 6634380Sbinkertn@umich.edu cxx_type = 'Addr' 6644380Sbinkertn@umich.edu size = 64 6654380Sbinkertn@umich.edu unsigned = True 6663101Sstever@eecs.umich.edu def __init__(self, value): 6673101Sstever@eecs.umich.edu if isinstance(value, Addr): 6683101Sstever@eecs.umich.edu self.value = value.value 6697673Snate@binkert.org else: 6707673Snate@binkert.org try: 6717673Snate@binkert.org # Often addresses are referred to with sizes. Ex: A device 6727673Snate@binkert.org # base address is at "512MB". Use toMemorySize() to convert 6737673Snate@binkert.org # these into addresses. If the address is not specified with a 6747673Snate@binkert.org # "size", an exception will occur and numeric translation will 6757673Snate@binkert.org # proceed below. 6767673Snate@binkert.org self.value = convert.toMemorySize(value) 6777673Snate@binkert.org except (TypeError, ValueError): 6783101Sstever@eecs.umich.edu # Convert number to string and use long() to do automatic 6793101Sstever@eecs.umich.edu # base conversion (requires base=0 for auto-conversion) 6803101Sstever@eecs.umich.edu self.value = long(str(value), base=0) 6813101Sstever@eecs.umich.edu 6823101Sstever@eecs.umich.edu self._check() 6833101Sstever@eecs.umich.edu def __add__(self, other): 6843101Sstever@eecs.umich.edu if isinstance(other, Addr): 6853101Sstever@eecs.umich.edu return self.value + other.value 6863101Sstever@eecs.umich.edu else: 6873101Sstever@eecs.umich.edu return self.value + other 6883101Sstever@eecs.umich.edu def pretty_print(self, value): 6893101Sstever@eecs.umich.edu try: 6903101Sstever@eecs.umich.edu val = convert.toMemorySize(value) 6917743Sgblack@eecs.umich.edu except TypeError: 6923101Sstever@eecs.umich.edu val = long(value) 6933101Sstever@eecs.umich.edu return "0x%x" % long(val) 6943101Sstever@eecs.umich.edu 6953101Sstever@eecs.umich.educlass AddrRange(ParamValue): 6963101Sstever@eecs.umich.edu cxx_type = 'AddrRange' 6973101Sstever@eecs.umich.edu 6984380Sbinkertn@umich.edu def __init__(self, *args, **kwargs): 6993101Sstever@eecs.umich.edu # Disable interleaving and hashing by default 7003101Sstever@eecs.umich.edu self.intlvHighBit = 0 7014762Snate@binkert.org self.xorHighBit = 0 7027677Snate@binkert.org self.intlvBits = 0 7034762Snate@binkert.org self.intlvMatch = 0 7044762Snate@binkert.org 7054380Sbinkertn@umich.edu def handle_kwargs(self, kwargs): 7064380Sbinkertn@umich.edu # An address range needs to have an upper limit, specified 7073101Sstever@eecs.umich.edu # either explicitly with an end, or as an offset using the 7087777Sgblack@eecs.umich.edu # size keyword. 7097777Sgblack@eecs.umich.edu if 'end' in kwargs: 7107777Sgblack@eecs.umich.edu self.end = Addr(kwargs.pop('end')) 7117777Sgblack@eecs.umich.edu elif 'size' in kwargs: 7127777Sgblack@eecs.umich.edu self.end = self.start + Addr(kwargs.pop('size')) - 1 7137777Sgblack@eecs.umich.edu else: 7147777Sgblack@eecs.umich.edu raise TypeError, "Either end or size must be specified" 7157777Sgblack@eecs.umich.edu 7167777Sgblack@eecs.umich.edu # Now on to the optional bit 7177777Sgblack@eecs.umich.edu if 'intlvHighBit' in kwargs: 7187777Sgblack@eecs.umich.edu self.intlvHighBit = int(kwargs.pop('intlvHighBit')) 7197777Sgblack@eecs.umich.edu if 'xorHighBit' in kwargs: 7207777Sgblack@eecs.umich.edu self.xorHighBit = int(kwargs.pop('xorHighBit')) 7217777Sgblack@eecs.umich.edu if 'intlvBits' in kwargs: 7227777Sgblack@eecs.umich.edu self.intlvBits = int(kwargs.pop('intlvBits')) 7237777Sgblack@eecs.umich.edu if 'intlvMatch' in kwargs: 7247777Sgblack@eecs.umich.edu self.intlvMatch = int(kwargs.pop('intlvMatch')) 7257777Sgblack@eecs.umich.edu 7267777Sgblack@eecs.umich.edu if len(args) == 0: 7277777Sgblack@eecs.umich.edu self.start = Addr(kwargs.pop('start')) 7287777Sgblack@eecs.umich.edu handle_kwargs(self, kwargs) 7297777Sgblack@eecs.umich.edu 7307777Sgblack@eecs.umich.edu elif len(args) == 1: 7318579Ssteve.reinhardt@amd.com if kwargs: 7328579Ssteve.reinhardt@amd.com self.start = Addr(args[0]) 7338579Ssteve.reinhardt@amd.com handle_kwargs(self, kwargs) 7348579Ssteve.reinhardt@amd.com elif isinstance(args[0], (list, tuple)): 7358579Ssteve.reinhardt@amd.com self.start = Addr(args[0][0]) 7368579Ssteve.reinhardt@amd.com self.end = Addr(args[0][1]) 7378579Ssteve.reinhardt@amd.com else: 7388579Ssteve.reinhardt@amd.com self.start = Addr(0) 7398579Ssteve.reinhardt@amd.com self.end = Addr(args[0]) - 1 7408579Ssteve.reinhardt@amd.com 7418579Ssteve.reinhardt@amd.com elif len(args) == 2: 7428579Ssteve.reinhardt@amd.com self.start = Addr(args[0]) 7438579Ssteve.reinhardt@amd.com self.end = Addr(args[1]) 7448579Ssteve.reinhardt@amd.com else: 7458579Ssteve.reinhardt@amd.com raise TypeError, "Too many arguments specified" 7468579Ssteve.reinhardt@amd.com 7478579Ssteve.reinhardt@amd.com if kwargs: 7488579Ssteve.reinhardt@amd.com raise TypeError, "Too many keywords: %s" % kwargs.keys() 7497777Sgblack@eecs.umich.edu 7507777Sgblack@eecs.umich.edu def __str__(self): 7517798Sgblack@eecs.umich.edu return '%s:%s:%s:%s:%s:%s' \ 7527777Sgblack@eecs.umich.edu % (self.start, self.end, self.intlvHighBit, self.xorHighBit,\ 7537777Sgblack@eecs.umich.edu self.intlvBits, self.intlvMatch) 7547777Sgblack@eecs.umich.edu 7557777Sgblack@eecs.umich.edu def size(self): 7567777Sgblack@eecs.umich.edu # Divide the size by the size of the interleaving slice 7577777Sgblack@eecs.umich.edu return (long(self.end) - long(self.start) + 1) >> self.intlvBits 7587777Sgblack@eecs.umich.edu 7597777Sgblack@eecs.umich.edu @classmethod 7607777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 7617777Sgblack@eecs.umich.edu Addr.cxx_predecls(code) 7627777Sgblack@eecs.umich.edu code('#include "base/addr_range.hh"') 7637777Sgblack@eecs.umich.edu 7647777Sgblack@eecs.umich.edu @classmethod 7657777Sgblack@eecs.umich.edu def pybind_predecls(cls, code): 7667777Sgblack@eecs.umich.edu Addr.pybind_predecls(code) 7677777Sgblack@eecs.umich.edu code('#include "base/addr_range.hh"') 7687777Sgblack@eecs.umich.edu 7697777Sgblack@eecs.umich.edu @classmethod 7707777Sgblack@eecs.umich.edu def cxx_ini_predecls(cls, code): 7717777Sgblack@eecs.umich.edu code('#include <sstream>') 7727777Sgblack@eecs.umich.edu 7737777Sgblack@eecs.umich.edu @classmethod 7747777Sgblack@eecs.umich.edu def cxx_ini_parse(cls, code, src, dest, ret): 7757777Sgblack@eecs.umich.edu code('uint64_t _start, _end, _intlvHighBit = 0, _xorHighBit = 0;') 7767777Sgblack@eecs.umich.edu code('uint64_t _intlvBits = 0, _intlvMatch = 0;') 7777777Sgblack@eecs.umich.edu code('char _sep;') 7787777Sgblack@eecs.umich.edu code('std::istringstream _stream(${src});') 7797777Sgblack@eecs.umich.edu code('_stream >> _start;') 7807777Sgblack@eecs.umich.edu code('_stream.get(_sep);') 7817777Sgblack@eecs.umich.edu code('_stream >> _end;') 7827777Sgblack@eecs.umich.edu code('if (!_stream.fail() && !_stream.eof()) {') 7837777Sgblack@eecs.umich.edu code(' _stream.get(_sep);') 7847777Sgblack@eecs.umich.edu code(' _stream >> _intlvHighBit;') 7857777Sgblack@eecs.umich.edu code(' _stream.get(_sep);') 7867777Sgblack@eecs.umich.edu code(' _stream >> _xorHighBit;') 7877777Sgblack@eecs.umich.edu code(' _stream.get(_sep);') 7887777Sgblack@eecs.umich.edu code(' _stream >> _intlvBits;') 7897777Sgblack@eecs.umich.edu code(' _stream.get(_sep);') 7907777Sgblack@eecs.umich.edu code(' _stream >> _intlvMatch;') 7917777Sgblack@eecs.umich.edu code('}') 7927777Sgblack@eecs.umich.edu code('bool _ret = !_stream.fail() &&' 7937777Sgblack@eecs.umich.edu '_stream.eof() && _sep == \':\';') 7947777Sgblack@eecs.umich.edu code('if (_ret)') 7957777Sgblack@eecs.umich.edu code(' ${dest} = AddrRange(_start, _end, _intlvHighBit, \ 7967777Sgblack@eecs.umich.edu _xorHighBit, _intlvBits, _intlvMatch);') 7977777Sgblack@eecs.umich.edu code('${ret} _ret;') 7987777Sgblack@eecs.umich.edu 7997777Sgblack@eecs.umich.edu def getValue(self): 8007777Sgblack@eecs.umich.edu # Go from the Python class to the wrapped C++ class 8017777Sgblack@eecs.umich.edu from _m5.range import AddrRange 8027777Sgblack@eecs.umich.edu 8037777Sgblack@eecs.umich.edu return AddrRange(long(self.start), long(self.end), 8047777Sgblack@eecs.umich.edu int(self.intlvHighBit), int(self.xorHighBit), 8057777Sgblack@eecs.umich.edu int(self.intlvBits), int(self.intlvMatch)) 8067777Sgblack@eecs.umich.edu 8078579Ssteve.reinhardt@amd.com# Boolean parameter type. Python doesn't let you subclass bool, since 8088579Ssteve.reinhardt@amd.com# it doesn't want to let you create multiple instances of True and 8098579Ssteve.reinhardt@amd.com# False. Thus this is a little more complicated than String. 8108579Ssteve.reinhardt@amd.comclass Bool(ParamValue): 8118579Ssteve.reinhardt@amd.com cxx_type = 'bool' 8128579Ssteve.reinhardt@amd.com cmd_line_settable = True 8138579Ssteve.reinhardt@amd.com 8148579Ssteve.reinhardt@amd.com def __init__(self, value): 8158579Ssteve.reinhardt@amd.com try: 8168579Ssteve.reinhardt@amd.com self.value = convert.toBool(value) 8178579Ssteve.reinhardt@amd.com except TypeError: 8188579Ssteve.reinhardt@amd.com self.value = bool(value) 8198579Ssteve.reinhardt@amd.com 8208579Ssteve.reinhardt@amd.com def __call__(self, value): 8217777Sgblack@eecs.umich.edu self.__init__(value) 8227777Sgblack@eecs.umich.edu return value 8237777Sgblack@eecs.umich.edu 8247777Sgblack@eecs.umich.edu def getValue(self): 8257777Sgblack@eecs.umich.edu return bool(self.value) 8267777Sgblack@eecs.umich.edu 8277777Sgblack@eecs.umich.edu def __str__(self): 8287777Sgblack@eecs.umich.edu return str(self.value) 8297777Sgblack@eecs.umich.edu 8307777Sgblack@eecs.umich.edu # implement truth value testing for Bool parameters so that these params 8317777Sgblack@eecs.umich.edu # evaluate correctly during the python configuration phase 8327777Sgblack@eecs.umich.edu def __nonzero__(self): 8337777Sgblack@eecs.umich.edu return bool(self.value) 8347777Sgblack@eecs.umich.edu 8357777Sgblack@eecs.umich.edu def ini_str(self): 8367777Sgblack@eecs.umich.edu if self.value: 8377777Sgblack@eecs.umich.edu return 'true' 8387777Sgblack@eecs.umich.edu return 'false' 8397777Sgblack@eecs.umich.edu 8407777Sgblack@eecs.umich.edu def config_value(self): 8417777Sgblack@eecs.umich.edu return self.value 8427777Sgblack@eecs.umich.edu 8437777Sgblack@eecs.umich.edu @classmethod 8447777Sgblack@eecs.umich.edu def cxx_ini_predecls(cls, code): 8457777Sgblack@eecs.umich.edu # Assume that base/str.hh will be included anyway 8467777Sgblack@eecs.umich.edu # code('#include "base/str.hh"') 8477777Sgblack@eecs.umich.edu pass 8487777Sgblack@eecs.umich.edu 8497777Sgblack@eecs.umich.edu @classmethod 8507777Sgblack@eecs.umich.edu def cxx_ini_parse(cls, code, src, dest, ret): 8517777Sgblack@eecs.umich.edu code('%s to_bool(%s, %s);' % (ret, src, dest)) 8527777Sgblack@eecs.umich.edu 8537777Sgblack@eecs.umich.edudef IncEthernetAddr(addr, val = 1): 8547777Sgblack@eecs.umich.edu bytes = map(lambda x: int(x, 16), addr.split(':')) 8557777Sgblack@eecs.umich.edu bytes[5] += val 8567777Sgblack@eecs.umich.edu for i in (5, 4, 3, 2, 1): 8577777Sgblack@eecs.umich.edu val,rem = divmod(bytes[i], 256) 8587777Sgblack@eecs.umich.edu bytes[i] = rem 8597777Sgblack@eecs.umich.edu if val == 0: 8607777Sgblack@eecs.umich.edu break 8617777Sgblack@eecs.umich.edu bytes[i - 1] += val 8627777Sgblack@eecs.umich.edu assert(bytes[0] <= 255) 8637777Sgblack@eecs.umich.edu return ':'.join(map(lambda x: '%02x' % x, bytes)) 8647777Sgblack@eecs.umich.edu 8657777Sgblack@eecs.umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 8667777Sgblack@eecs.umich.edudef NextEthernetAddr(): 8677777Sgblack@eecs.umich.edu global _NextEthernetAddr 8687777Sgblack@eecs.umich.edu 8697777Sgblack@eecs.umich.edu value = _NextEthernetAddr 8707777Sgblack@eecs.umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 8717777Sgblack@eecs.umich.edu return value 8727777Sgblack@eecs.umich.edu 8737777Sgblack@eecs.umich.educlass EthernetAddr(ParamValue): 8747777Sgblack@eecs.umich.edu cxx_type = 'Net::EthAddr' 8757777Sgblack@eecs.umich.edu ex_str = "00:90:00:00:00:01" 8767777Sgblack@eecs.umich.edu cmd_line_settable = True 8777777Sgblack@eecs.umich.edu 8787777Sgblack@eecs.umich.edu @classmethod 8798579Ssteve.reinhardt@amd.com def cxx_predecls(cls, code): 8808579Ssteve.reinhardt@amd.com code('#include "base/inet.hh"') 8818579Ssteve.reinhardt@amd.com 8828579Ssteve.reinhardt@amd.com def __init__(self, value): 8838579Ssteve.reinhardt@amd.com if value == NextEthernetAddr: 8848579Ssteve.reinhardt@amd.com self.value = value 8858579Ssteve.reinhardt@amd.com return 8868579Ssteve.reinhardt@amd.com 8878579Ssteve.reinhardt@amd.com if not isinstance(value, str): 8888579Ssteve.reinhardt@amd.com raise TypeError, "expected an ethernet address and didn't get one" 8898579Ssteve.reinhardt@amd.com 8908579Ssteve.reinhardt@amd.com bytes = value.split(':') 8918579Ssteve.reinhardt@amd.com if len(bytes) != 6: 8928579Ssteve.reinhardt@amd.com raise TypeError, 'invalid ethernet address %s' % value 8937777Sgblack@eecs.umich.edu 8947777Sgblack@eecs.umich.edu for byte in bytes: 8957777Sgblack@eecs.umich.edu if not 0 <= int(byte, base=16) <= 0xff: 8967777Sgblack@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 8977777Sgblack@eecs.umich.edu 8987777Sgblack@eecs.umich.edu self.value = value 8997777Sgblack@eecs.umich.edu 9007777Sgblack@eecs.umich.edu def __call__(self, value): 9017777Sgblack@eecs.umich.edu self.__init__(value) 9023932Sbinkertn@umich.edu return value 9033932Sbinkertn@umich.edu 9043932Sbinkertn@umich.edu def unproxy(self, base): 9053932Sbinkertn@umich.edu if self.value == NextEthernetAddr: 9063932Sbinkertn@umich.edu return EthernetAddr(self.value()) 9073932Sbinkertn@umich.edu return self 9083932Sbinkertn@umich.edu 9093932Sbinkertn@umich.edu def getValue(self): 9103932Sbinkertn@umich.edu from _m5.net import EthAddr 9113932Sbinkertn@umich.edu return EthAddr(self.value) 9123932Sbinkertn@umich.edu 9133932Sbinkertn@umich.edu def __str__(self): 9143932Sbinkertn@umich.edu return self.value 9153885Sbinkertn@umich.edu 9163932Sbinkertn@umich.edu def ini_str(self): 9173932Sbinkertn@umich.edu return self.value 9183885Sbinkertn@umich.edu 9193932Sbinkertn@umich.edu @classmethod 9203932Sbinkertn@umich.edu def cxx_ini_parse(self, code, src, dest, ret): 9213932Sbinkertn@umich.edu code('%s = Net::EthAddr(%s);' % (dest, src)) 9223932Sbinkertn@umich.edu code('%s true;' % ret) 9233932Sbinkertn@umich.edu 9243932Sbinkertn@umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of 9253932Sbinkertn@umich.edu# the form "a.b.c.d", or an integer representing an IP. 9263932Sbinkertn@umich.educlass IpAddress(ParamValue): 9273932Sbinkertn@umich.edu cxx_type = 'Net::IpAddress' 9283932Sbinkertn@umich.edu ex_str = "127.0.0.1" 9293932Sbinkertn@umich.edu cmd_line_settable = True 9303932Sbinkertn@umich.edu 9313932Sbinkertn@umich.edu @classmethod 9323932Sbinkertn@umich.edu def cxx_predecls(cls, code): 9333932Sbinkertn@umich.edu code('#include "base/inet.hh"') 9343932Sbinkertn@umich.edu 9353932Sbinkertn@umich.edu def __init__(self, value): 9363932Sbinkertn@umich.edu if isinstance(value, IpAddress): 9373885Sbinkertn@umich.edu self.ip = value.ip 9383885Sbinkertn@umich.edu else: 9393885Sbinkertn@umich.edu try: 9403885Sbinkertn@umich.edu self.ip = convert.toIpAddress(value) 9414762Snate@binkert.org except TypeError: 9427673Snate@binkert.org self.ip = long(value) 9437673Snate@binkert.org self.verifyIp() 9447673Snate@binkert.org 9457673Snate@binkert.org def __call__(self, value): 9467673Snate@binkert.org self.__init__(value) 9477673Snate@binkert.org return value 9487673Snate@binkert.org 9497673Snate@binkert.org def __str__(self): 9507673Snate@binkert.org tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)] 9513885Sbinkertn@umich.edu return '%d.%d.%d.%d' % tuple(tup) 9523932Sbinkertn@umich.edu 9533885Sbinkertn@umich.edu def __eq__(self, other): 9544762Snate@binkert.org if isinstance(other, IpAddress): 9557677Snate@binkert.org return self.ip == other.ip 9564762Snate@binkert.org elif isinstance(other, str): 9574762Snate@binkert.org try: 9584762Snate@binkert.org return self.ip == convert.toIpAddress(other) 9594762Snate@binkert.org except: 9604762Snate@binkert.org return False 9614762Snate@binkert.org else: 9624762Snate@binkert.org return self.ip == other 9634762Snate@binkert.org 9644762Snate@binkert.org def __ne__(self, other): 9654762Snate@binkert.org return not (self == other) 9664762Snate@binkert.org 9674762Snate@binkert.org def verifyIp(self): 9684762Snate@binkert.org if self.ip < 0 or self.ip >= (1 << 32): 9694762Snate@binkert.org raise TypeError, "invalid ip address %#08x" % self.ip 9704762Snate@binkert.org 9714762Snate@binkert.org def getValue(self): 9724762Snate@binkert.org from _m5.net import IpAddress 9734762Snate@binkert.org return IpAddress(self.ip) 9744762Snate@binkert.org 9754762Snate@binkert.org# When initializing an IpNetmask, pass in an existing IpNetmask, a string of 9764762Snate@binkert.org# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as 9774762Snate@binkert.org# positional or keyword arguments. 9784762Snate@binkert.orgclass IpNetmask(IpAddress): 9794762Snate@binkert.org cxx_type = 'Net::IpNetmask' 9803885Sbinkertn@umich.edu ex_str = "127.0.0.0/24" 9814762Snate@binkert.org cmd_line_settable = True 9823885Sbinkertn@umich.edu 9833885Sbinkertn@umich.edu @classmethod 9843932Sbinkertn@umich.edu def cxx_predecls(cls, code): 9853885Sbinkertn@umich.edu code('#include "base/inet.hh"') 9868664SAli.Saidi@ARM.com 9878664SAli.Saidi@ARM.com def __init__(self, *args, **kwargs): 9888664SAli.Saidi@ARM.com def handle_kwarg(self, kwargs, key, elseVal = None): 9893101Sstever@eecs.umich.edu if key in kwargs: 9903101Sstever@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 9913101Sstever@eecs.umich.edu elif elseVal: 9923101Sstever@eecs.umich.edu setattr(self, key, elseVal) 9933101Sstever@eecs.umich.edu else: 9943101Sstever@eecs.umich.edu raise TypeError, "No value set for %s" % key 9953101Sstever@eecs.umich.edu 9963101Sstever@eecs.umich.edu if len(args) == 0: 9973101Sstever@eecs.umich.edu handle_kwarg(self, kwargs, 'ip') 9983101Sstever@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask') 9993101Sstever@eecs.umich.edu 10003101Sstever@eecs.umich.edu elif len(args) == 1: 10013101Sstever@eecs.umich.edu if kwargs: 10023101Sstever@eecs.umich.edu if not 'ip' in kwargs and not 'netmask' in kwargs: 10034762Snate@binkert.org raise TypeError, "Invalid arguments" 10043101Sstever@eecs.umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 10055033Smilesck@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask', args[0]) 10064762Snate@binkert.org elif isinstance(args[0], IpNetmask): 10074762Snate@binkert.org self.ip = args[0].ip 10084762Snate@binkert.org self.netmask = args[0].netmask 10094762Snate@binkert.org else: 10104762Snate@binkert.org (self.ip, self.netmask) = convert.toIpNetmask(args[0]) 10114762Snate@binkert.org 10124762Snate@binkert.org elif len(args) == 2: 10133101Sstever@eecs.umich.edu self.ip = args[0] 10143101Sstever@eecs.umich.edu self.netmask = args[1] 10153101Sstever@eecs.umich.edu else: 10163101Sstever@eecs.umich.edu raise TypeError, "Too many arguments specified" 10173101Sstever@eecs.umich.edu 10183101Sstever@eecs.umich.edu if kwargs: 10193101Sstever@eecs.umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 10203101Sstever@eecs.umich.edu 10213101Sstever@eecs.umich.edu self.verify() 10223101Sstever@eecs.umich.edu 10233101Sstever@eecs.umich.edu def __call__(self, value): 10243101Sstever@eecs.umich.edu self.__init__(value) 10253101Sstever@eecs.umich.edu return value 10263101Sstever@eecs.umich.edu 10273101Sstever@eecs.umich.edu def __str__(self): 10283101Sstever@eecs.umich.edu return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask) 10293101Sstever@eecs.umich.edu 10303101Sstever@eecs.umich.edu def __eq__(self, other): 10313101Sstever@eecs.umich.edu if isinstance(other, IpNetmask): 10323101Sstever@eecs.umich.edu return self.ip == other.ip and self.netmask == other.netmask 10334762Snate@binkert.org elif isinstance(other, str): 10343101Sstever@eecs.umich.edu try: 10353101Sstever@eecs.umich.edu return (self.ip, self.netmask) == convert.toIpNetmask(other) 10363101Sstever@eecs.umich.edu except: 10373101Sstever@eecs.umich.edu return False 10383101Sstever@eecs.umich.edu else: 10393101Sstever@eecs.umich.edu return False 10407673Snate@binkert.org 10416654Snate@binkert.org def verify(self): 10427673Snate@binkert.org self.verifyIp() 10437673Snate@binkert.org if self.netmask < 0 or self.netmask > 32: 10447673Snate@binkert.org raise TypeError, "invalid netmask %d" % netmask 10457673Snate@binkert.org 10467673Snate@binkert.org def getValue(self): 10477673Snate@binkert.org from _m5.net import IpNetmask 10487673Snate@binkert.org return IpNetmask(self.ip, self.netmask) 10497673Snate@binkert.org 10504762Snate@binkert.org# When initializing an IpWithPort, pass in an existing IpWithPort, a string of 10517673Snate@binkert.org# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments. 10527673Snate@binkert.orgclass IpWithPort(IpAddress): 10537673Snate@binkert.org cxx_type = 'Net::IpWithPort' 10547673Snate@binkert.org ex_str = "127.0.0.1:80" 10557673Snate@binkert.org cmd_line_settable = True 10567673Snate@binkert.org 10577673Snate@binkert.org @classmethod 10584762Snate@binkert.org def cxx_predecls(cls, code): 10597673Snate@binkert.org code('#include "base/inet.hh"') 10607673Snate@binkert.org 10617673Snate@binkert.org def __init__(self, *args, **kwargs): 10627673Snate@binkert.org def handle_kwarg(self, kwargs, key, elseVal = None): 10636654Snate@binkert.org if key in kwargs: 10647673Snate@binkert.org setattr(self, key, kwargs.pop(key)) 10657677Snate@binkert.org elif elseVal: 10667673Snate@binkert.org setattr(self, key, elseVal) 10677673Snate@binkert.org else: 10687673Snate@binkert.org raise TypeError, "No value set for %s" % key 10697673Snate@binkert.org 10707673Snate@binkert.org if len(args) == 0: 10714762Snate@binkert.org handle_kwarg(self, kwargs, 'ip') 10727673Snate@binkert.org handle_kwarg(self, kwargs, 'port') 10737673Snate@binkert.org 10747673Snate@binkert.org elif len(args) == 1: 10757673Snate@binkert.org if kwargs: 10767811Ssteve.reinhardt@amd.com if not 'ip' in kwargs and not 'port' in kwargs: 10777673Snate@binkert.org raise TypeError, "Invalid arguments" 10783101Sstever@eecs.umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 10798596Ssteve.reinhardt@amd.com handle_kwarg(self, kwargs, 'port', args[0]) 10808596Ssteve.reinhardt@amd.com elif isinstance(args[0], IpWithPort): 10818596Ssteve.reinhardt@amd.com self.ip = args[0].ip 10828596Ssteve.reinhardt@amd.com self.port = args[0].port 10838596Ssteve.reinhardt@amd.com else: 10848596Ssteve.reinhardt@amd.com (self.ip, self.port) = convert.toIpWithPort(args[0]) 10858596Ssteve.reinhardt@amd.com 10868596Ssteve.reinhardt@amd.com elif len(args) == 2: 10878596Ssteve.reinhardt@amd.com self.ip = args[0] 10888596Ssteve.reinhardt@amd.com self.port = args[1] 10898596Ssteve.reinhardt@amd.com else: 10908596Ssteve.reinhardt@amd.com raise TypeError, "Too many arguments specified" 10918596Ssteve.reinhardt@amd.com 10923101Sstever@eecs.umich.edu if kwargs: 10933101Sstever@eecs.umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 10943101Sstever@eecs.umich.edu 10953101Sstever@eecs.umich.edu self.verify() 10963101Sstever@eecs.umich.edu 10973101Sstever@eecs.umich.edu def __call__(self, value): 10983101Sstever@eecs.umich.edu self.__init__(value) 10993101Sstever@eecs.umich.edu return value 11003101Sstever@eecs.umich.edu 11013101Sstever@eecs.umich.edu def __str__(self): 11023101Sstever@eecs.umich.edu return "%s:%d" % (super(IpWithPort, self).__str__(), self.port) 11037675Snate@binkert.org 11047675Snate@binkert.org def __eq__(self, other): 11057675Snate@binkert.org if isinstance(other, IpWithPort): 11067675Snate@binkert.org return self.ip == other.ip and self.port == other.port 11077675Snate@binkert.org elif isinstance(other, str): 11087675Snate@binkert.org try: 11097677Snate@binkert.org return (self.ip, self.port) == convert.toIpWithPort(other) 11107675Snate@binkert.org except: 11114762Snate@binkert.org return False 11124762Snate@binkert.org else: 11134762Snate@binkert.org return False 11143101Sstever@eecs.umich.edu 11153101Sstever@eecs.umich.edu def verify(self): 11163101Sstever@eecs.umich.edu self.verifyIp() 11173101Sstever@eecs.umich.edu if self.port < 0 or self.port > 0xffff: 11183101Sstever@eecs.umich.edu raise TypeError, "invalid port %d" % self.port 11193101Sstever@eecs.umich.edu 11204167Sbinkertn@umich.edu def getValue(self): 11213101Sstever@eecs.umich.edu from _m5.net import IpWithPort 11227673Snate@binkert.org return IpWithPort(self.ip, self.port) 11237673Snate@binkert.org 11247673Snate@binkert.orgtime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 11257673Snate@binkert.org "%a %b %d %H:%M:%S %Y", 11267673Snate@binkert.org "%Y/%m/%d %H:%M:%S", 11277673Snate@binkert.org "%Y/%m/%d %H:%M", 11287673Snate@binkert.org "%Y/%m/%d", 11297673Snate@binkert.org "%m/%d/%Y %H:%M:%S", 11307673Snate@binkert.org "%m/%d/%Y %H:%M", 11314167Sbinkertn@umich.edu "%m/%d/%Y", 11324762Snate@binkert.org "%m/%d/%y %H:%M:%S", 11334762Snate@binkert.org "%m/%d/%y %H:%M", 11344762Snate@binkert.org "%m/%d/%y"] 11354167Sbinkertn@umich.edu 11363101Sstever@eecs.umich.edu 11374167Sbinkertn@umich.edudef parse_time(value): 11384167Sbinkertn@umich.edu from time import gmtime, strptime, struct_time, time 11394167Sbinkertn@umich.edu from datetime import datetime, date 11404167Sbinkertn@umich.edu 11414167Sbinkertn@umich.edu if isinstance(value, struct_time): 11424167Sbinkertn@umich.edu return value 11434167Sbinkertn@umich.edu 11444167Sbinkertn@umich.edu if isinstance(value, (int, long)): 11454167Sbinkertn@umich.edu return gmtime(value) 11464167Sbinkertn@umich.edu 11474167Sbinkertn@umich.edu if isinstance(value, (datetime, date)): 11484167Sbinkertn@umich.edu return value.timetuple() 11493101Sstever@eecs.umich.edu 11503101Sstever@eecs.umich.edu if isinstance(value, str): 11513101Sstever@eecs.umich.edu if value in ('Now', 'Today'): 11523101Sstever@eecs.umich.edu return time.gmtime(time.time()) 11533101Sstever@eecs.umich.edu 11543101Sstever@eecs.umich.edu for format in time_formats: 11553101Sstever@eecs.umich.edu try: 11563101Sstever@eecs.umich.edu return strptime(value, format) 11574762Snate@binkert.org except ValueError: 11584762Snate@binkert.org pass 11594762Snate@binkert.org 11604762Snate@binkert.org raise ValueError, "Could not parse '%s' as a time" % value 11614762Snate@binkert.org 11624762Snate@binkert.orgclass Time(ParamValue): 11634762Snate@binkert.org cxx_type = 'tm' 11643101Sstever@eecs.umich.edu 11653101Sstever@eecs.umich.edu @classmethod 11664762Snate@binkert.org def cxx_predecls(cls, code): 11673101Sstever@eecs.umich.edu code('#include <time.h>') 11684167Sbinkertn@umich.edu 11693101Sstever@eecs.umich.edu def __init__(self, value): 11704167Sbinkertn@umich.edu self.value = parse_time(value) 11714167Sbinkertn@umich.edu 11724167Sbinkertn@umich.edu def __call__(self, value): 11734167Sbinkertn@umich.edu self.__init__(value) 11744167Sbinkertn@umich.edu return value 11754167Sbinkertn@umich.edu 11764167Sbinkertn@umich.edu def getValue(self): 11774167Sbinkertn@umich.edu from _m5.core import tm 11784167Sbinkertn@umich.edu import calendar 11794167Sbinkertn@umich.edu 11804167Sbinkertn@umich.edu return tm.gmtime(calendar.timegm(self.value)) 11814167Sbinkertn@umich.edu 11823101Sstever@eecs.umich.edu def __str__(self): 11833101Sstever@eecs.umich.edu return time.asctime(self.value) 11843101Sstever@eecs.umich.edu 11853101Sstever@eecs.umich.edu def ini_str(self): 11863101Sstever@eecs.umich.edu return str(self) 11873101Sstever@eecs.umich.edu 11883101Sstever@eecs.umich.edu def get_config_as_dict(self): 11893101Sstever@eecs.umich.edu assert false 11904167Sbinkertn@umich.edu return str(self) 11914762Snate@binkert.org 11924762Snate@binkert.org @classmethod 11934762Snate@binkert.org def cxx_ini_predecls(cls, code): 11944762Snate@binkert.org code('#include <time.h>') 11954762Snate@binkert.org 11964762Snate@binkert.org @classmethod 11974762Snate@binkert.org def cxx_ini_parse(cls, code, src, dest, ret): 11983101Sstever@eecs.umich.edu code('char *_parse_ret = strptime((${src}).c_str(),') 11994762Snate@binkert.org code(' "%a %b %d %H:%M:%S %Y", &(${dest}));') 12003101Sstever@eecs.umich.edu code('${ret} _parse_ret && *_parse_ret == \'\\0\';'); 12013101Sstever@eecs.umich.edu 12023101Sstever@eecs.umich.edu# Enumerated types are a little more complex. The user specifies the 12033101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of 12043101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so). (In the 12053101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index 12067673Snate@binkert.org# or the corresponding dictionary value. For now, since we only check 12077673Snate@binkert.org# that the alternative is valid and then spit it into a .ini file, 12087673Snate@binkert.org# there's not much point in using the dictionary.) 12097673Snate@binkert.org 12107673Snate@binkert.org# What Enum() must do is generate a new type encapsulating the 12117673Snate@binkert.org# provided list/dictionary so that specific values of the parameter 12127673Snate@binkert.org# can be instances of that type. We define two hidden internal 12137673Snate@binkert.org# classes (_ListEnum and _DictEnum) to serve as base classes, then 12147673Snate@binkert.org# derive the new type from the appropriate base class on the fly. 12157673Snate@binkert.org 12163101Sstever@eecs.umich.eduallEnums = {} 12174167Sbinkertn@umich.edu# Metaclass for Enum types 12184167Sbinkertn@umich.educlass MetaEnum(MetaParamValue): 12194167Sbinkertn@umich.edu def __new__(mcls, name, bases, dict): 12204167Sbinkertn@umich.edu assert name not in allEnums 12214167Sbinkertn@umich.edu 12224167Sbinkertn@umich.edu cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 12234167Sbinkertn@umich.edu allEnums[name] = cls 12244167Sbinkertn@umich.edu return cls 12254167Sbinkertn@umich.edu 12264167Sbinkertn@umich.edu def __init__(cls, name, bases, init_dict): 12274167Sbinkertn@umich.edu if init_dict.has_key('map'): 12284167Sbinkertn@umich.edu if not isinstance(cls.map, dict): 12293101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'map' " \ 12303101Sstever@eecs.umich.edu "must be of type dict" 12313101Sstever@eecs.umich.edu # build list of value strings from map 12323101Sstever@eecs.umich.edu cls.vals = cls.map.keys() 12333101Sstever@eecs.umich.edu cls.vals.sort() 12343101Sstever@eecs.umich.edu elif init_dict.has_key('vals'): 12353101Sstever@eecs.umich.edu if not isinstance(cls.vals, list): 12363101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'vals' " \ 12374762Snate@binkert.org "must be of type list" 12384762Snate@binkert.org # build string->value map from vals sequence 12394762Snate@binkert.org cls.map = {} 12403101Sstever@eecs.umich.edu for idx,val in enumerate(cls.vals): 12413101Sstever@eecs.umich.edu cls.map[val] = idx 12423101Sstever@eecs.umich.edu else: 12433101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class must define "\ 12443101Sstever@eecs.umich.edu "attribute 'map' or 'vals'" 12453101Sstever@eecs.umich.edu 12464167Sbinkertn@umich.edu cls.cxx_type = 'Enums::%s' % name 12474167Sbinkertn@umich.edu 12483101Sstever@eecs.umich.edu super(MetaEnum, cls).__init__(name, bases, init_dict) 12493101Sstever@eecs.umich.edu 12503101Sstever@eecs.umich.edu # Generate C++ class declaration for this enum type. 12513101Sstever@eecs.umich.edu # Note that we wrap the enum in a class/struct to act as a namespace, 12523101Sstever@eecs.umich.edu # so that the enum strings can be brief w/o worrying about collisions. 12534762Snate@binkert.org def cxx_decl(cls, code): 12544167Sbinkertn@umich.edu wrapper_name = cls.wrapper_name 12554167Sbinkertn@umich.edu wrapper = 'struct' if cls.wrapper_is_struct else 'namespace' 12564167Sbinkertn@umich.edu name = cls.__name__ if cls.enum_name is None else cls.enum_name 12574762Snate@binkert.org idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name) 12584762Snate@binkert.org 12594762Snate@binkert.org code('''\ 12604762Snate@binkert.org#ifndef $idem_macro 12614762Snate@binkert.org#define $idem_macro 12623101Sstever@eecs.umich.edu 12633101Sstever@eecs.umich.edu$wrapper $wrapper_name { 12643101Sstever@eecs.umich.edu enum $name { 12655469Snate@binkert.org''') 12667743Sgblack@eecs.umich.edu code.indent(2) 12673102Sstever@eecs.umich.edu for val in cls.vals: 12683101Sstever@eecs.umich.edu code('$val = ${{cls.map[val]}},') 12693101Sstever@eecs.umich.edu code('Num_$name = ${{len(cls.vals)}}') 12703101Sstever@eecs.umich.edu code.dedent(2) 12713101Sstever@eecs.umich.edu code(' };') 12723101Sstever@eecs.umich.edu 12734762Snate@binkert.org if cls.wrapper_is_struct: 12744167Sbinkertn@umich.edu code(' static const char *${name}Strings[Num_${name}];') 12755468Snate@binkert.org code('};') 12765468Snate@binkert.org else: 12775468Snate@binkert.org code('extern const char *${name}Strings[Num_${name}];') 12784167Sbinkertn@umich.edu code('}') 12794762Snate@binkert.org 12804762Snate@binkert.org code() 12814762Snate@binkert.org code('#endif // $idem_macro') 12824762Snate@binkert.org 12834762Snate@binkert.org def cxx_def(cls, code): 12843101Sstever@eecs.umich.edu wrapper_name = cls.wrapper_name 12853101Sstever@eecs.umich.edu file_name = cls.__name__ 12863101Sstever@eecs.umich.edu name = cls.__name__ if cls.enum_name is None else cls.enum_name 12873101Sstever@eecs.umich.edu 12883101Sstever@eecs.umich.edu code('#include "enums/$file_name.hh"') 12893102Sstever@eecs.umich.edu if cls.wrapper_is_struct: 12903102Sstever@eecs.umich.edu code('const char *${wrapper_name}::${name}Strings' 12913102Sstever@eecs.umich.edu '[Num_${name}] =') 12923102Sstever@eecs.umich.edu else: 12933102Sstever@eecs.umich.edu code('namespace Enums {') 12943102Sstever@eecs.umich.edu code.indent(1) 12953102Sstever@eecs.umich.edu code(' const char *${name}Strings[Num_${name}] =') 12963102Sstever@eecs.umich.edu 12973102Sstever@eecs.umich.edu code('{') 12983102Sstever@eecs.umich.edu code.indent(1) 12993102Sstever@eecs.umich.edu for val in cls.vals: 13003102Sstever@eecs.umich.edu code('"$val",') 13013102Sstever@eecs.umich.edu code.dedent(1) 13023102Sstever@eecs.umich.edu code('};') 13033102Sstever@eecs.umich.edu 13043102Sstever@eecs.umich.edu if not cls.wrapper_is_struct: 13053102Sstever@eecs.umich.edu code('} // namespace $wrapper_name') 13063102Sstever@eecs.umich.edu code.dedent(1) 13073102Sstever@eecs.umich.edu 13083102Sstever@eecs.umich.edu def pybind_def(cls, code): 13093102Sstever@eecs.umich.edu name = cls.__name__ 13104762Snate@binkert.org wrapper_name = cls.wrapper_name 13113102Sstever@eecs.umich.edu enum_name = cls.__name__ if cls.enum_name is None else cls.enum_name 13123102Sstever@eecs.umich.edu 13133102Sstever@eecs.umich.edu code('''#include "pybind11/pybind11.h" 13144762Snate@binkert.org#include "pybind11/stl.h" 13154762Snate@binkert.org 13164762Snate@binkert.org#include <sim/init.hh> 13173102Sstever@eecs.umich.edu 13183102Sstever@eecs.umich.edunamespace py = pybind11; 13193102Sstever@eecs.umich.edu 13203102Sstever@eecs.umich.edustatic void 13213102Sstever@eecs.umich.edumodule_init(py::module &m_internal) 13223102Sstever@eecs.umich.edu{ 13233101Sstever@eecs.umich.edu py::module m = m_internal.def_submodule("enum_${name}"); 13243101Sstever@eecs.umich.edu 13253101Sstever@eecs.umich.edu py::enum_<${wrapper_name}::${enum_name}>(m, "enum_${name}") 13263101Sstever@eecs.umich.edu''') 13273101Sstever@eecs.umich.edu 13283101Sstever@eecs.umich.edu code.indent() 13293101Sstever@eecs.umich.edu code.indent() 13303101Sstever@eecs.umich.edu for val in cls.vals: 13313101Sstever@eecs.umich.edu code('.value("${val}", ${wrapper_name}::${val})') 13323101Sstever@eecs.umich.edu code('.value("Num_${name}", ${wrapper_name}::Num_${enum_name})') 13333101Sstever@eecs.umich.edu code('.export_values()') 13343101Sstever@eecs.umich.edu code(';') 13353101Sstever@eecs.umich.edu code.dedent() 13363101Sstever@eecs.umich.edu 13373101Sstever@eecs.umich.edu code('}') 13383101Sstever@eecs.umich.edu code.dedent() 13393101Sstever@eecs.umich.edu code() 13408839Sandreas.hansson@arm.com code('static EmbeddedPyBind embed_enum("enum_${name}", module_init);') 13413105Sstever@eecs.umich.edu 13423101Sstever@eecs.umich.edu 13433101Sstever@eecs.umich.edu# Base class for enum types. 13448839Sandreas.hansson@arm.comclass Enum(ParamValue): 13453101Sstever@eecs.umich.edu __metaclass__ = MetaEnum 13463101Sstever@eecs.umich.edu vals = [] 13473105Sstever@eecs.umich.edu cmd_line_settable = True 13483101Sstever@eecs.umich.edu 13493103Sstever@eecs.umich.edu # The name of the wrapping namespace or struct 13503105Sstever@eecs.umich.edu wrapper_name = 'Enums' 13513103Sstever@eecs.umich.edu 13528840Sandreas.hansson@arm.com # If true, the enum is wrapped in a struct rather than a namespace 13538840Sandreas.hansson@arm.com wrapper_is_struct = False 13548840Sandreas.hansson@arm.com 13558840Sandreas.hansson@arm.com # If not None, use this as the enum name rather than this class name 13568840Sandreas.hansson@arm.com enum_name = None 13573105Sstever@eecs.umich.edu 13583105Sstever@eecs.umich.edu def __init__(self, value): 13593105Sstever@eecs.umich.edu if value not in self.map: 13603105Sstever@eecs.umich.edu raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 13613105Sstever@eecs.umich.edu % (value, self.vals) 13623105Sstever@eecs.umich.edu self.value = value 13633105Sstever@eecs.umich.edu 13643105Sstever@eecs.umich.edu def __call__(self, value): 13653105Sstever@eecs.umich.edu self.__init__(value) 13663105Sstever@eecs.umich.edu return value 13673105Sstever@eecs.umich.edu 13683105Sstever@eecs.umich.edu @classmethod 13693105Sstever@eecs.umich.edu def cxx_predecls(cls, code): 13703109Sstever@eecs.umich.edu code('#include "enums/$0.hh"', cls.__name__) 13713105Sstever@eecs.umich.edu 13723105Sstever@eecs.umich.edu @classmethod 13733105Sstever@eecs.umich.edu def cxx_ini_parse(cls, code, src, dest, ret): 13743105Sstever@eecs.umich.edu code('if (false) {') 13753105Sstever@eecs.umich.edu for elem_name in cls.map.iterkeys(): 13763105Sstever@eecs.umich.edu code('} else if (%s == "%s") {' % (src, elem_name)) 13773105Sstever@eecs.umich.edu code.indent() 13783105Sstever@eecs.umich.edu code('%s = Enums::%s;' % (dest, elem_name)) 13795578SSteve.Reinhardt@amd.com code('%s true;' % ret) 13803101Sstever@eecs.umich.edu code.dedent() 13813109Sstever@eecs.umich.edu code('} else {') 13823109Sstever@eecs.umich.edu code(' %s false;' % ret) 13833109Sstever@eecs.umich.edu code('}') 13843109Sstever@eecs.umich.edu 13853109Sstever@eecs.umich.edu def getValue(self): 13863109Sstever@eecs.umich.edu import m5.internal.params 13873109Sstever@eecs.umich.edu e = getattr(m5.internal.params, "enum_%s" % self.__class__.__name__) 13883109Sstever@eecs.umich.edu return e(self.map[self.value]) 13893109Sstever@eecs.umich.edu 13903101Sstever@eecs.umich.edu def __str__(self): 13913105Sstever@eecs.umich.edu return self.value 13923105Sstever@eecs.umich.edu 13933105Sstever@eecs.umich.edu# how big does a rounding error need to be before we warn about it? 13943101Sstever@eecs.umich.edufrequency_tolerance = 0.001 # 0.1% 13953105Sstever@eecs.umich.edu 13963105Sstever@eecs.umich.educlass TickParamValue(NumericParamValue): 13973101Sstever@eecs.umich.edu cxx_type = 'Tick' 13983105Sstever@eecs.umich.edu ex_str = "1MHz" 13993179Sstever@eecs.umich.edu cmd_line_settable = True 14003105Sstever@eecs.umich.edu 14013105Sstever@eecs.umich.edu @classmethod 14023101Sstever@eecs.umich.edu def cxx_predecls(cls, code): 14033101Sstever@eecs.umich.edu code('#include "base/types.hh"') 14043105Sstever@eecs.umich.edu 14053105Sstever@eecs.umich.edu def __call__(self, value): 14063105Sstever@eecs.umich.edu self.__init__(value) 14073105Sstever@eecs.umich.edu return value 14083105Sstever@eecs.umich.edu 14093105Sstever@eecs.umich.edu def getValue(self): 14103105Sstever@eecs.umich.edu return long(self.value) 14113105Sstever@eecs.umich.edu 14123105Sstever@eecs.umich.edu @classmethod 14133105Sstever@eecs.umich.edu def cxx_ini_predecls(cls, code): 14143105Sstever@eecs.umich.edu code('#include <sstream>') 14153101Sstever@eecs.umich.edu 14163101Sstever@eecs.umich.edu # Ticks are expressed in seconds in JSON files and in plain 14178597Ssteve.reinhardt@amd.com # Ticks in .ini files. Switch based on a config flag 14184762Snate@binkert.org @classmethod 14198839Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 14208839Sandreas.hansson@arm.com code('${ret} to_number(${src}, ${dest});') 14218839Sandreas.hansson@arm.com 14228839Sandreas.hansson@arm.comclass Latency(TickParamValue): 14233101Sstever@eecs.umich.edu ex_str = "100ns" 14243101Sstever@eecs.umich.edu 14253101Sstever@eecs.umich.edu def __init__(self, value): 14265578SSteve.Reinhardt@amd.com if isinstance(value, (Latency, Clock)): 14275578SSteve.Reinhardt@amd.com self.ticks = value.ticks 14288839Sandreas.hansson@arm.com self.value = value.value 14298839Sandreas.hansson@arm.com elif isinstance(value, Frequency): 14308839Sandreas.hansson@arm.com self.ticks = value.ticks 14318839Sandreas.hansson@arm.com self.value = 1.0 / value.value 14328839Sandreas.hansson@arm.com elif value.endswith('t'): 14338839Sandreas.hansson@arm.com self.ticks = True 14348839Sandreas.hansson@arm.com self.value = int(value[:-1]) 14357526Ssteve.reinhardt@amd.com else: 14368839Sandreas.hansson@arm.com self.ticks = False 14377526Ssteve.reinhardt@amd.com self.value = convert.toLatency(value) 14387526Ssteve.reinhardt@amd.com 14397526Ssteve.reinhardt@amd.com def __call__(self, value): 14407526Ssteve.reinhardt@amd.com self.__init__(value) 14417526Ssteve.reinhardt@amd.com return value 14427526Ssteve.reinhardt@amd.com 14437526Ssteve.reinhardt@amd.com def __getattr__(self, attr): 14443101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 14453101Sstever@eecs.umich.edu return self 14463101Sstever@eecs.umich.edu if attr == 'frequency': 14473105Sstever@eecs.umich.edu return Frequency(self) 14483105Sstever@eecs.umich.edu raise AttributeError, "Latency object has no attribute '%s'" % attr 14493105Sstever@eecs.umich.edu 14508839Sandreas.hansson@arm.com def getValue(self): 14518839Sandreas.hansson@arm.com if self.ticks or self.value == 0: 14523105Sstever@eecs.umich.edu value = self.value 14533105Sstever@eecs.umich.edu else: 14543105Sstever@eecs.umich.edu value = ticks.fromSeconds(self.value) 14553105Sstever@eecs.umich.edu return long(value) 14563105Sstever@eecs.umich.edu 14573105Sstever@eecs.umich.edu def config_value(self): 14583105Sstever@eecs.umich.edu return self.getValue() 14593105Sstever@eecs.umich.edu 14608839Sandreas.hansson@arm.com # convert latency to ticks 14613105Sstever@eecs.umich.edu def ini_str(self): 14623105Sstever@eecs.umich.edu return '%d' % self.getValue() 14633105Sstever@eecs.umich.edu 14648839Sandreas.hansson@arm.comclass Frequency(TickParamValue): 14653105Sstever@eecs.umich.edu ex_str = "1GHz" 14663105Sstever@eecs.umich.edu 14673109Sstever@eecs.umich.edu def __init__(self, value): 14683109Sstever@eecs.umich.edu if isinstance(value, (Latency, Clock)): 14693109Sstever@eecs.umich.edu if value.value == 0: 14708840Sandreas.hansson@arm.com self.value = 0 14718840Sandreas.hansson@arm.com else: 14728840Sandreas.hansson@arm.com self.value = 1.0 / value.value 14738840Sandreas.hansson@arm.com self.ticks = value.ticks 14748840Sandreas.hansson@arm.com elif isinstance(value, Frequency): 14753105Sstever@eecs.umich.edu self.value = value.value 14763105Sstever@eecs.umich.edu self.ticks = value.ticks 14773105Sstever@eecs.umich.edu else: 14783105Sstever@eecs.umich.edu self.ticks = False 14793105Sstever@eecs.umich.edu self.value = convert.toFrequency(value) 14803105Sstever@eecs.umich.edu 14813105Sstever@eecs.umich.edu def __call__(self, value): 14823105Sstever@eecs.umich.edu self.__init__(value) 14833105Sstever@eecs.umich.edu return value 14848839Sandreas.hansson@arm.com 14853105Sstever@eecs.umich.edu def __getattr__(self, attr): 14863105Sstever@eecs.umich.edu if attr == 'frequency': 14873105Sstever@eecs.umich.edu return self 14883105Sstever@eecs.umich.edu if attr in ('latency', 'period'): 14893105Sstever@eecs.umich.edu return Latency(self) 14903105Sstever@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 14913105Sstever@eecs.umich.edu 14923105Sstever@eecs.umich.edu # convert latency to ticks 14933105Sstever@eecs.umich.edu def getValue(self): 14943105Sstever@eecs.umich.edu if self.ticks or self.value == 0: 14953105Sstever@eecs.umich.edu value = self.value 14963105Sstever@eecs.umich.edu else: 14973105Sstever@eecs.umich.edu value = ticks.fromSeconds(1.0 / self.value) 14983109Sstever@eecs.umich.edu return long(value) 14993109Sstever@eecs.umich.edu 15003109Sstever@eecs.umich.edu def config_value(self): 15013109Sstever@eecs.umich.edu return self.getValue() 15023109Sstever@eecs.umich.edu 15033109Sstever@eecs.umich.edu def ini_str(self): 15043109Sstever@eecs.umich.edu return '%d' % self.getValue() 15053109Sstever@eecs.umich.edu 15063109Sstever@eecs.umich.edu# A generic Frequency and/or Latency value. Value is stored as a 15073109Sstever@eecs.umich.edu# latency, just like Latency and Frequency. 15083109Sstever@eecs.umich.educlass Clock(TickParamValue): 15093109Sstever@eecs.umich.edu def __init__(self, value): 15103109Sstever@eecs.umich.edu if isinstance(value, (Latency, Clock)): 15113109Sstever@eecs.umich.edu self.ticks = value.ticks 15123109Sstever@eecs.umich.edu self.value = value.value 15133109Sstever@eecs.umich.edu elif isinstance(value, Frequency): 15143109Sstever@eecs.umich.edu self.ticks = value.ticks 15153109Sstever@eecs.umich.edu self.value = 1.0 / value.value 15163109Sstever@eecs.umich.edu elif value.endswith('t'): 15173105Sstever@eecs.umich.edu self.ticks = True 15183105Sstever@eecs.umich.edu self.value = int(value[:-1]) 15193105Sstever@eecs.umich.edu else: 15203105Sstever@eecs.umich.edu self.ticks = False 15213105Sstever@eecs.umich.edu self.value = convert.anyToLatency(value) 15223105Sstever@eecs.umich.edu 15233105Sstever@eecs.umich.edu def __call__(self, value): 15243101Sstever@eecs.umich.edu self.__init__(value) 15253101Sstever@eecs.umich.edu return value 15263101Sstever@eecs.umich.edu 15273101Sstever@eecs.umich.edu def __str__(self): 15283101Sstever@eecs.umich.edu return "%s" % Latency(self) 15293101Sstever@eecs.umich.edu 15303105Sstever@eecs.umich.edu def __getattr__(self, attr): 15318839Sandreas.hansson@arm.com if attr == 'frequency': 15323101Sstever@eecs.umich.edu return Frequency(self) 15333101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 15343101Sstever@eecs.umich.edu return Latency(self) 15353105Sstever@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 15363105Sstever@eecs.umich.edu 15373101Sstever@eecs.umich.edu def getValue(self): 15388840Sandreas.hansson@arm.com return self.period.getValue() 15398840Sandreas.hansson@arm.com 15408840Sandreas.hansson@arm.com def config_value(self): 15418840Sandreas.hansson@arm.com return self.period.config_value() 15428840Sandreas.hansson@arm.com 15438840Sandreas.hansson@arm.com def ini_str(self): 15448840Sandreas.hansson@arm.com return self.period.ini_str() 15458840Sandreas.hansson@arm.com 15468840Sandreas.hansson@arm.comclass Voltage(Float): 15478840Sandreas.hansson@arm.com ex_str = "1V" 15488840Sandreas.hansson@arm.com 15498839Sandreas.hansson@arm.com def __new__(cls, value): 15508839Sandreas.hansson@arm.com value = convert.toVoltage(value) 15518839Sandreas.hansson@arm.com return super(cls, Voltage).__new__(cls, value) 15528839Sandreas.hansson@arm.com 15538839Sandreas.hansson@arm.com def __init__(self, value): 15548839Sandreas.hansson@arm.com value = convert.toVoltage(value) 15558839Sandreas.hansson@arm.com super(Voltage, self).__init__(value) 15568839Sandreas.hansson@arm.com 15578839Sandreas.hansson@arm.comclass Current(Float): 15588839Sandreas.hansson@arm.com ex_str = "1mA" 15598839Sandreas.hansson@arm.com 15608839Sandreas.hansson@arm.com def __new__(cls, value): 15618839Sandreas.hansson@arm.com value = convert.toCurrent(value) 15628839Sandreas.hansson@arm.com return super(cls, Current).__new__(cls, value) 15638839Sandreas.hansson@arm.com 15648839Sandreas.hansson@arm.com def __init__(self, value): 15658839Sandreas.hansson@arm.com value = convert.toCurrent(value) 15668839Sandreas.hansson@arm.com super(Current, self).__init__(value) 15673101Sstever@eecs.umich.edu 15683101Sstever@eecs.umich.educlass Energy(Float): 15693101Sstever@eecs.umich.edu ex_str = "1pJ" 15703105Sstever@eecs.umich.edu 15713101Sstever@eecs.umich.edu def __new__(cls, value): 15723101Sstever@eecs.umich.edu value = convert.toEnergy(value) 15733105Sstever@eecs.umich.edu return super(cls, Energy).__new__(cls, value) 15748839Sandreas.hansson@arm.com 15758839Sandreas.hansson@arm.com def __init__(self, value): 15768839Sandreas.hansson@arm.com value = convert.toEnergy(value) 15778839Sandreas.hansson@arm.com super(Energy, self).__init__(value) 15788839Sandreas.hansson@arm.com 15798839Sandreas.hansson@arm.comclass NetworkBandwidth(float,ParamValue): 15808839Sandreas.hansson@arm.com cxx_type = 'float' 15818839Sandreas.hansson@arm.com ex_str = "1Gbps" 15828839Sandreas.hansson@arm.com cmd_line_settable = True 15838839Sandreas.hansson@arm.com 15848839Sandreas.hansson@arm.com def __new__(cls, value): 15858839Sandreas.hansson@arm.com # convert to bits per second 15868839Sandreas.hansson@arm.com val = convert.toNetworkBandwidth(value) 15878839Sandreas.hansson@arm.com return super(cls, NetworkBandwidth).__new__(cls, val) 15888839Sandreas.hansson@arm.com 15898839Sandreas.hansson@arm.com def __str__(self): 15908839Sandreas.hansson@arm.com return str(self.val) 15918839Sandreas.hansson@arm.com 15928839Sandreas.hansson@arm.com def __call__(self, value): 15938839Sandreas.hansson@arm.com val = convert.toNetworkBandwidth(value) 15948839Sandreas.hansson@arm.com self.__init__(val) 15953105Sstever@eecs.umich.edu return value 15963109Sstever@eecs.umich.edu 15973109Sstever@eecs.umich.edu def getValue(self): 15983109Sstever@eecs.umich.edu # convert to seconds per byte 15993109Sstever@eecs.umich.edu value = 8.0 / float(self) 16003109Sstever@eecs.umich.edu # convert to ticks per byte 16013109Sstever@eecs.umich.edu value = ticks.fromSeconds(value) 16023109Sstever@eecs.umich.edu return float(value) 16033109Sstever@eecs.umich.edu 16043105Sstever@eecs.umich.edu def ini_str(self): 16056654Snate@binkert.org return '%f' % self.getValue() 16066654Snate@binkert.org 16076654Snate@binkert.org def config_value(self): 16086654Snate@binkert.org return '%f' % self.getValue() 16096654Snate@binkert.org 16106654Snate@binkert.org @classmethod 16116654Snate@binkert.org def cxx_ini_predecls(cls, code): 16126654Snate@binkert.org code('#include <sstream>') 16136654Snate@binkert.org 16143101Sstever@eecs.umich.edu @classmethod 16153101Sstever@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 16163101Sstever@eecs.umich.edu code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 16173101Sstever@eecs.umich.edu 16183101Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue): 16193101Sstever@eecs.umich.edu cxx_type = 'float' 16207777Sgblack@eecs.umich.edu ex_str = "1GB/s" 16213101Sstever@eecs.umich.edu cmd_line_settable = True 16224167Sbinkertn@umich.edu 16233101Sstever@eecs.umich.edu def __new__(cls, value): 16243101Sstever@eecs.umich.edu # convert to bytes per second 16253101Sstever@eecs.umich.edu val = convert.toMemoryBandwidth(value) 16263885Sbinkertn@umich.edu return super(cls, MemoryBandwidth).__new__(cls, val) 16273102Sstever@eecs.umich.edu 16288839Sandreas.hansson@arm.com def __call__(self, value): 16298839Sandreas.hansson@arm.com val = convert.toMemoryBandwidth(value) 16306654Snate@binkert.org self.__init__(val) 16316654Snate@binkert.org return value 1632 1633 def getValue(self): 1634 # convert to seconds per byte 1635 value = float(self) 1636 if value: 1637 value = 1.0 / float(self) 1638 # convert to ticks per byte 1639 value = ticks.fromSeconds(value) 1640 return float(value) 1641 1642 def ini_str(self): 1643 return '%f' % self.getValue() 1644 1645 def config_value(self): 1646 return '%f' % self.getValue() 1647 1648 @classmethod 1649 def cxx_ini_predecls(cls, code): 1650 code('#include <sstream>') 1651 1652 @classmethod 1653 def cxx_ini_parse(self, code, src, dest, ret): 1654 code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 1655 1656# 1657# "Constants"... handy aliases for various values. 1658# 1659 1660# Special class for NULL pointers. Note the special check in 1661# make_param_value() above that lets these be assigned where a 1662# SimObject is required. 1663# only one copy of a particular node 1664class NullSimObject(object): 1665 __metaclass__ = Singleton 1666 _name = 'Null' 1667 1668 def __call__(cls): 1669 return cls 1670 1671 def _instantiate(self, parent = None, path = ''): 1672 pass 1673 1674 def ini_str(self): 1675 return 'Null' 1676 1677 def unproxy(self, base): 1678 return self 1679 1680 def set_path(self, parent, name): 1681 pass 1682 1683 def set_parent(self, parent, name): 1684 pass 1685 1686 def clear_parent(self, old_parent): 1687 pass 1688 1689 def descendants(self): 1690 return 1691 yield None 1692 1693 def get_config_as_dict(self): 1694 return {} 1695 1696 def __str__(self): 1697 return self._name 1698 1699 def config_value(self): 1700 return None 1701 1702 def getValue(self): 1703 return None 1704 1705# The only instance you'll ever need... 1706NULL = NullSimObject() 1707 1708def isNullPointer(value): 1709 return isinstance(value, NullSimObject) 1710 1711# Some memory range specifications use this as a default upper bound. 1712MaxAddr = Addr.max 1713MaxTick = Tick.max 1714AllMemory = AddrRange(0, MaxAddr) 1715 1716 1717##################################################################### 1718# 1719# Port objects 1720# 1721# Ports are used to interconnect objects in the memory system. 1722# 1723##################################################################### 1724 1725# Port reference: encapsulates a reference to a particular port on a 1726# particular SimObject. 1727class PortRef(object): 1728 def __init__(self, simobj, name, role): 1729 assert(isSimObject(simobj) or isSimObjectClass(simobj)) 1730 self.simobj = simobj 1731 self.name = name 1732 self.role = role 1733 self.peer = None # not associated with another port yet 1734 self.ccConnected = False # C++ port connection done? 1735 self.index = -1 # always -1 for non-vector ports 1736 1737 def __str__(self): 1738 return '%s.%s' % (self.simobj, self.name) 1739 1740 def __len__(self): 1741 # Return the number of connected ports, i.e. 0 is we have no 1742 # peer and 1 if we do. 1743 return int(self.peer != None) 1744 1745 # for config.ini, print peer's name (not ours) 1746 def ini_str(self): 1747 return str(self.peer) 1748 1749 # for config.json 1750 def get_config_as_dict(self): 1751 return {'role' : self.role, 'peer' : str(self.peer)} 1752 1753 def __getattr__(self, attr): 1754 if attr == 'peerObj': 1755 # shorthand for proxies 1756 return self.peer.simobj 1757 raise AttributeError, "'%s' object has no attribute '%s'" % \ 1758 (self.__class__.__name__, attr) 1759 1760 # Full connection is symmetric (both ways). Called via 1761 # SimObject.__setattr__ as a result of a port assignment, e.g., 1762 # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 1763 # e.g., "obj1.portA[3] = obj2.portB". 1764 def connect(self, other): 1765 if isinstance(other, VectorPortRef): 1766 # reference to plain VectorPort is implicit append 1767 other = other._get_next() 1768 if self.peer and not proxy.isproxy(self.peer): 1769 fatal("Port %s is already connected to %s, cannot connect %s\n", 1770 self, self.peer, other); 1771 self.peer = other 1772 if proxy.isproxy(other): 1773 other.set_param_desc(PortParamDesc()) 1774 elif isinstance(other, PortRef): 1775 if other.peer is not self: 1776 other.connect(self) 1777 else: 1778 raise TypeError, \ 1779 "assigning non-port reference '%s' to port '%s'" \ 1780 % (other, self) 1781 1782 # Allow a master/slave port pair to be spliced between 1783 # a port and its connected peer. Useful operation for connecting 1784 # instrumentation structures into a system when it is necessary 1785 # to connect the instrumentation after the full system has been 1786 # constructed. 1787 def splice(self, new_master_peer, new_slave_peer): 1788 if self.peer and not proxy.isproxy(self.peer): 1789 if isinstance(new_master_peer, PortRef) and \ 1790 isinstance(new_slave_peer, PortRef): 1791 old_peer = self.peer 1792 if self.role == 'SLAVE': 1793 self.peer = new_master_peer 1794 old_peer.peer = new_slave_peer 1795 new_master_peer.connect(self) 1796 new_slave_peer.connect(old_peer) 1797 elif self.role == 'MASTER': 1798 self.peer = new_slave_peer 1799 old_peer.peer = new_master_peer 1800 new_slave_peer.connect(self) 1801 new_master_peer.connect(old_peer) 1802 else: 1803 panic("Port %s has unknown role, "+\ 1804 "cannot splice in new peers\n", self) 1805 else: 1806 raise TypeError, \ 1807 "Splicing non-port references '%s','%s' to port '%s'"\ 1808 % (new_master_peer, new_slave_peer, self) 1809 else: 1810 fatal("Port %s not connected, cannot splice in new peers\n", self) 1811 1812 def clone(self, simobj, memo): 1813 if memo.has_key(self): 1814 return memo[self] 1815 newRef = copy.copy(self) 1816 memo[self] = newRef 1817 newRef.simobj = simobj 1818 assert(isSimObject(newRef.simobj)) 1819 if self.peer and not proxy.isproxy(self.peer): 1820 peerObj = self.peer.simobj(_memo=memo) 1821 newRef.peer = self.peer.clone(peerObj, memo) 1822 assert(not isinstance(newRef.peer, VectorPortRef)) 1823 return newRef 1824 1825 def unproxy(self, simobj): 1826 assert(simobj is self.simobj) 1827 if proxy.isproxy(self.peer): 1828 try: 1829 realPeer = self.peer.unproxy(self.simobj) 1830 except: 1831 print("Error in unproxying port '%s' of %s" % 1832 (self.name, self.simobj.path())) 1833 raise 1834 self.connect(realPeer) 1835 1836 # Call C++ to create corresponding port connection between C++ objects 1837 def ccConnect(self): 1838 from _m5.pyobject import connectPorts 1839 1840 if self.role == 'SLAVE': 1841 # do nothing and let the master take care of it 1842 return 1843 1844 if self.ccConnected: # already done this 1845 return 1846 peer = self.peer 1847 if not self.peer: # nothing to connect to 1848 return 1849 1850 # check that we connect a master to a slave 1851 if self.role == peer.role: 1852 raise TypeError, \ 1853 "cannot connect '%s' and '%s' due to identical role '%s'" \ 1854 % (peer, self, self.role) 1855 1856 try: 1857 # self is always the master and peer the slave 1858 connectPorts(self.simobj.getCCObject(), self.name, self.index, 1859 peer.simobj.getCCObject(), peer.name, peer.index) 1860 except: 1861 print("Error connecting port %s.%s to %s.%s" % 1862 (self.simobj.path(), self.name, 1863 peer.simobj.path(), peer.name)) 1864 raise 1865 self.ccConnected = True 1866 peer.ccConnected = True 1867 1868# A reference to an individual element of a VectorPort... much like a 1869# PortRef, but has an index. 1870class VectorPortElementRef(PortRef): 1871 def __init__(self, simobj, name, role, index): 1872 PortRef.__init__(self, simobj, name, role) 1873 self.index = index 1874 1875 def __str__(self): 1876 return '%s.%s[%d]' % (self.simobj, self.name, self.index) 1877 1878# A reference to a complete vector-valued port (not just a single element). 1879# Can be indexed to retrieve individual VectorPortElementRef instances. 1880class VectorPortRef(object): 1881 def __init__(self, simobj, name, role): 1882 assert(isSimObject(simobj) or isSimObjectClass(simobj)) 1883 self.simobj = simobj 1884 self.name = name 1885 self.role = role 1886 self.elements = [] 1887 1888 def __str__(self): 1889 return '%s.%s[:]' % (self.simobj, self.name) 1890 1891 def __len__(self): 1892 # Return the number of connected peers, corresponding the the 1893 # length of the elements. 1894 return len(self.elements) 1895 1896 # for config.ini, print peer's name (not ours) 1897 def ini_str(self): 1898 return ' '.join([el.ini_str() for el in self.elements]) 1899 1900 # for config.json 1901 def get_config_as_dict(self): 1902 return {'role' : self.role, 1903 'peer' : [el.ini_str() for el in self.elements]} 1904 1905 def __getitem__(self, key): 1906 if not isinstance(key, int): 1907 raise TypeError, "VectorPort index must be integer" 1908 if key >= len(self.elements): 1909 # need to extend list 1910 ext = [VectorPortElementRef(self.simobj, self.name, self.role, i) 1911 for i in range(len(self.elements), key+1)] 1912 self.elements.extend(ext) 1913 return self.elements[key] 1914 1915 def _get_next(self): 1916 return self[len(self.elements)] 1917 1918 def __setitem__(self, key, value): 1919 if not isinstance(key, int): 1920 raise TypeError, "VectorPort index must be integer" 1921 self[key].connect(value) 1922 1923 def connect(self, other): 1924 if isinstance(other, (list, tuple)): 1925 # Assign list of port refs to vector port. 1926 # For now, append them... not sure if that's the right semantics 1927 # or if it should replace the current vector. 1928 for ref in other: 1929 self._get_next().connect(ref) 1930 else: 1931 # scalar assignment to plain VectorPort is implicit append 1932 self._get_next().connect(other) 1933 1934 def clone(self, simobj, memo): 1935 if memo.has_key(self): 1936 return memo[self] 1937 newRef = copy.copy(self) 1938 memo[self] = newRef 1939 newRef.simobj = simobj 1940 assert(isSimObject(newRef.simobj)) 1941 newRef.elements = [el.clone(simobj, memo) for el in self.elements] 1942 return newRef 1943 1944 def unproxy(self, simobj): 1945 [el.unproxy(simobj) for el in self.elements] 1946 1947 def ccConnect(self): 1948 [el.ccConnect() for el in self.elements] 1949 1950# Port description object. Like a ParamDesc object, this represents a 1951# logical port in the SimObject class, not a particular port on a 1952# SimObject instance. The latter are represented by PortRef objects. 1953class Port(object): 1954 # Generate a PortRef for this port on the given SimObject with the 1955 # given name 1956 def makeRef(self, simobj): 1957 return PortRef(simobj, self.name, self.role) 1958 1959 # Connect an instance of this port (on the given SimObject with 1960 # the given name) with the port described by the supplied PortRef 1961 def connect(self, simobj, ref): 1962 self.makeRef(simobj).connect(ref) 1963 1964 # No need for any pre-declarations at the moment as we merely rely 1965 # on an unsigned int. 1966 def cxx_predecls(self, code): 1967 pass 1968 1969 def pybind_predecls(self, code): 1970 cls.cxx_predecls(self, code) 1971 1972 # Declare an unsigned int with the same name as the port, that 1973 # will eventually hold the number of connected ports (and thus the 1974 # number of elements for a VectorPort). 1975 def cxx_decl(self, code): 1976 code('unsigned int port_${{self.name}}_connection_count;') 1977 1978class MasterPort(Port): 1979 # MasterPort("description") 1980 def __init__(self, *args): 1981 if len(args) == 1: 1982 self.desc = args[0] 1983 self.role = 'MASTER' 1984 else: 1985 raise TypeError, 'wrong number of arguments' 1986 1987class SlavePort(Port): 1988 # SlavePort("description") 1989 def __init__(self, *args): 1990 if len(args) == 1: 1991 self.desc = args[0] 1992 self.role = 'SLAVE' 1993 else: 1994 raise TypeError, 'wrong number of arguments' 1995 1996# VectorPort description object. Like Port, but represents a vector 1997# of connections (e.g., as on a XBar). 1998class VectorPort(Port): 1999 def __init__(self, *args): 2000 self.isVec = True 2001 2002 def makeRef(self, simobj): 2003 return VectorPortRef(simobj, self.name, self.role) 2004 2005class VectorMasterPort(VectorPort): 2006 # VectorMasterPort("description") 2007 def __init__(self, *args): 2008 if len(args) == 1: 2009 self.desc = args[0] 2010 self.role = 'MASTER' 2011 VectorPort.__init__(self, *args) 2012 else: 2013 raise TypeError, 'wrong number of arguments' 2014 2015class VectorSlavePort(VectorPort): 2016 # VectorSlavePort("description") 2017 def __init__(self, *args): 2018 if len(args) == 1: 2019 self.desc = args[0] 2020 self.role = 'SLAVE' 2021 VectorPort.__init__(self, *args) 2022 else: 2023 raise TypeError, 'wrong number of arguments' 2024 2025# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 2026# proxy objects (via set_param_desc()) so that proxy error messages 2027# make sense. 2028class PortParamDesc(object): 2029 __metaclass__ = Singleton 2030 2031 ptype_str = 'Port' 2032 ptype = Port 2033 2034baseEnums = allEnums.copy() 2035baseParams = allParams.copy() 2036 2037def clear(): 2038 global allEnums, allParams 2039 2040 allEnums = baseEnums.copy() 2041 allParams = baseParams.copy() 2042 2043__all__ = ['Param', 'VectorParam', 2044 'Enum', 'Bool', 'String', 'Float', 2045 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 2046 'Int32', 'UInt32', 'Int64', 'UInt64', 2047 'Counter', 'Addr', 'Tick', 'Percent', 2048 'TcpPort', 'UdpPort', 'EthernetAddr', 2049 'IpAddress', 'IpNetmask', 'IpWithPort', 2050 'MemorySize', 'MemorySize32', 2051 'Latency', 'Frequency', 'Clock', 'Voltage', 'Current', 'Energy', 2052 'NetworkBandwidth', 'MemoryBandwidth', 2053 'AddrRange', 2054 'MaxAddr', 'MaxTick', 'AllMemory', 2055 'Time', 2056 'NextEthernetAddr', 'NULL', 2057 'MasterPort', 'SlavePort', 2058 'VectorMasterPort', 'VectorSlavePort'] 2059 2060import SimObject 2061