params.py revision 11802
110355SGeoffrey.Blake@arm.com# Copyright (c) 2012-2014 ARM Limited 28839Sandreas.hansson@arm.com# All rights reserved. 38839Sandreas.hansson@arm.com# 48839Sandreas.hansson@arm.com# The license below extends only to copyright in the software and shall 58839Sandreas.hansson@arm.com# not be construed as granting a license to any other intellectual 68839Sandreas.hansson@arm.com# property including but not limited to intellectual property relating 78839Sandreas.hansson@arm.com# to a hardware implementation of the functionality of the software 88839Sandreas.hansson@arm.com# licensed hereunder. You may use the software subject to the license 98839Sandreas.hansson@arm.com# terms below provided that you ensure that this notice is replicated 108839Sandreas.hansson@arm.com# unmodified and in its entirety in all distributions of the software, 118839Sandreas.hansson@arm.com# modified or unmodified, in source code or in binary form. 128839Sandreas.hansson@arm.com# 133101Sstever@eecs.umich.edu# Copyright (c) 2004-2006 The Regents of The University of Michigan 148579Ssteve.reinhardt@amd.com# Copyright (c) 2010-2011 Advanced Micro Devices, Inc. 153101Sstever@eecs.umich.edu# All rights reserved. 163101Sstever@eecs.umich.edu# 173101Sstever@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 183101Sstever@eecs.umich.edu# modification, are permitted provided that the following conditions are 193101Sstever@eecs.umich.edu# met: redistributions of source code must retain the above copyright 203101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 213101Sstever@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 223101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 233101Sstever@eecs.umich.edu# documentation and/or other materials provided with the distribution; 243101Sstever@eecs.umich.edu# neither the name of the copyright holders nor the names of its 253101Sstever@eecs.umich.edu# contributors may be used to endorse or promote products derived from 263101Sstever@eecs.umich.edu# this software without specific prior written permission. 273101Sstever@eecs.umich.edu# 283101Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 293101Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 303101Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 313101Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 323101Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 333101Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 343101Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 353101Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 363101Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 373101Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 383101Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 393101Sstever@eecs.umich.edu# 403101Sstever@eecs.umich.edu# Authors: Steve Reinhardt 413101Sstever@eecs.umich.edu# Nathan Binkert 427778Sgblack@eecs.umich.edu# Gabe Black 438839Sandreas.hansson@arm.com# Andreas Hansson 443101Sstever@eecs.umich.edu 453101Sstever@eecs.umich.edu##################################################################### 463101Sstever@eecs.umich.edu# 473101Sstever@eecs.umich.edu# Parameter description classes 483101Sstever@eecs.umich.edu# 493101Sstever@eecs.umich.edu# The _params dictionary in each class maps parameter names to either 503101Sstever@eecs.umich.edu# a Param or a VectorParam object. These objects contain the 513101Sstever@eecs.umich.edu# parameter description string, the parameter type, and the default 523101Sstever@eecs.umich.edu# value (if any). The convert() method on these objects is used to 533101Sstever@eecs.umich.edu# force whatever value is assigned to the parameter to the appropriate 543101Sstever@eecs.umich.edu# type. 553101Sstever@eecs.umich.edu# 563101Sstever@eecs.umich.edu# Note that the default values are loaded into the class's attribute 573101Sstever@eecs.umich.edu# space when the parameter dictionary is initialized (in 583101Sstever@eecs.umich.edu# MetaSimObject._new_param()); after that point they aren't used. 593101Sstever@eecs.umich.edu# 603101Sstever@eecs.umich.edu##################################################################### 613101Sstever@eecs.umich.edu 623885Sbinkertn@umich.eduimport copy 633885Sbinkertn@umich.eduimport datetime 644762Snate@binkert.orgimport re 653885Sbinkertn@umich.eduimport sys 663885Sbinkertn@umich.eduimport time 677528Ssteve.reinhardt@amd.comimport math 683885Sbinkertn@umich.edu 694380Sbinkertn@umich.eduimport proxy 704167Sbinkertn@umich.eduimport ticks 713102Sstever@eecs.umich.edufrom util import * 723101Sstever@eecs.umich.edu 734762Snate@binkert.orgdef isSimObject(*args, **kwargs): 744762Snate@binkert.org return SimObject.isSimObject(*args, **kwargs) 754762Snate@binkert.org 764762Snate@binkert.orgdef isSimObjectSequence(*args, **kwargs): 774762Snate@binkert.org return SimObject.isSimObjectSequence(*args, **kwargs) 784762Snate@binkert.org 794762Snate@binkert.orgdef isSimObjectClass(*args, **kwargs): 804762Snate@binkert.org return SimObject.isSimObjectClass(*args, **kwargs) 814762Snate@binkert.org 825033Smilesck@eecs.umich.eduallParams = {} 835033Smilesck@eecs.umich.edu 845033Smilesck@eecs.umich.educlass MetaParamValue(type): 855033Smilesck@eecs.umich.edu def __new__(mcls, name, bases, dct): 865033Smilesck@eecs.umich.edu cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) 875033Smilesck@eecs.umich.edu assert name not in allParams 885033Smilesck@eecs.umich.edu allParams[name] = cls 895033Smilesck@eecs.umich.edu return cls 905033Smilesck@eecs.umich.edu 915033Smilesck@eecs.umich.edu 923101Sstever@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject 933101Sstever@eecs.umich.edu# parameters. 943101Sstever@eecs.umich.educlass ParamValue(object): 955033Smilesck@eecs.umich.edu __metaclass__ = MetaParamValue 9610267SGeoffrey.Blake@arm.com cmd_line_settable = False 978596Ssteve.reinhardt@amd.com 988596Ssteve.reinhardt@amd.com # Generate the code needed as a prerequisite for declaring a C++ 998596Ssteve.reinhardt@amd.com # object of this type. Typically generates one or more #include 1008596Ssteve.reinhardt@amd.com # statements. Used when declaring parameters of this type. 1017673Snate@binkert.org @classmethod 1027673Snate@binkert.org def cxx_predecls(cls, code): 1037673Snate@binkert.org pass 1047673Snate@binkert.org 1058596Ssteve.reinhardt@amd.com # Generate the code needed as a prerequisite for including a 1068596Ssteve.reinhardt@amd.com # reference to a C++ object of this type in a SWIG .i file. 1078596Ssteve.reinhardt@amd.com # Typically generates one or more %import or %include statements. 1087673Snate@binkert.org @classmethod 1097673Snate@binkert.org def swig_predecls(cls, code): 1107673Snate@binkert.org pass 1113101Sstever@eecs.umich.edu 1123101Sstever@eecs.umich.edu # default for printing to .ini file is regular string conversion. 1133101Sstever@eecs.umich.edu # will be overridden in some cases 1143101Sstever@eecs.umich.edu def ini_str(self): 1153101Sstever@eecs.umich.edu return str(self) 1163101Sstever@eecs.umich.edu 11710380SAndrew.Bardsley@arm.com # default for printing to .json file is regular string conversion. 11810380SAndrew.Bardsley@arm.com # will be overridden in some cases, mostly to use native Python 11910380SAndrew.Bardsley@arm.com # types where there are similar JSON types 12010380SAndrew.Bardsley@arm.com def config_value(self): 12110380SAndrew.Bardsley@arm.com return str(self) 12210380SAndrew.Bardsley@arm.com 12310458Sandreas.hansson@arm.com # Prerequisites for .ini parsing with cxx_ini_parse 12410458Sandreas.hansson@arm.com @classmethod 12510458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 12610458Sandreas.hansson@arm.com pass 12710458Sandreas.hansson@arm.com 12810458Sandreas.hansson@arm.com # parse a .ini file entry for this param from string expression 12910458Sandreas.hansson@arm.com # src into lvalue dest (of the param's C++ type) 13010458Sandreas.hansson@arm.com @classmethod 13110458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 13210458Sandreas.hansson@arm.com code('// Unhandled param type: %s' % cls.__name__) 13310458Sandreas.hansson@arm.com code('%s false;' % ret) 13410458Sandreas.hansson@arm.com 1353101Sstever@eecs.umich.edu # allows us to blithely call unproxy() on things without checking 1363101Sstever@eecs.umich.edu # if they're really proxies or not 1373101Sstever@eecs.umich.edu def unproxy(self, base): 1383101Sstever@eecs.umich.edu return self 1393101Sstever@eecs.umich.edu 14010267SGeoffrey.Blake@arm.com # Produce a human readable version of the stored value 14110267SGeoffrey.Blake@arm.com def pretty_print(self, value): 14210267SGeoffrey.Blake@arm.com return str(value) 14310267SGeoffrey.Blake@arm.com 1443101Sstever@eecs.umich.edu# Regular parameter description. 1453101Sstever@eecs.umich.educlass ParamDesc(object): 1463101Sstever@eecs.umich.edu def __init__(self, ptype_str, ptype, *args, **kwargs): 1473101Sstever@eecs.umich.edu self.ptype_str = ptype_str 1483101Sstever@eecs.umich.edu # remember ptype only if it is provided 1493101Sstever@eecs.umich.edu if ptype != None: 1503101Sstever@eecs.umich.edu self.ptype = ptype 1513101Sstever@eecs.umich.edu 1523101Sstever@eecs.umich.edu if args: 1533101Sstever@eecs.umich.edu if len(args) == 1: 1543101Sstever@eecs.umich.edu self.desc = args[0] 1553101Sstever@eecs.umich.edu elif len(args) == 2: 1563101Sstever@eecs.umich.edu self.default = args[0] 1573101Sstever@eecs.umich.edu self.desc = args[1] 1583101Sstever@eecs.umich.edu else: 1593101Sstever@eecs.umich.edu raise TypeError, 'too many arguments' 1603101Sstever@eecs.umich.edu 1613101Sstever@eecs.umich.edu if kwargs.has_key('desc'): 1623101Sstever@eecs.umich.edu assert(not hasattr(self, 'desc')) 1633101Sstever@eecs.umich.edu self.desc = kwargs['desc'] 1643101Sstever@eecs.umich.edu del kwargs['desc'] 1653101Sstever@eecs.umich.edu 1663101Sstever@eecs.umich.edu if kwargs.has_key('default'): 1673101Sstever@eecs.umich.edu assert(not hasattr(self, 'default')) 1683101Sstever@eecs.umich.edu self.default = kwargs['default'] 1693101Sstever@eecs.umich.edu del kwargs['default'] 1703101Sstever@eecs.umich.edu 1713101Sstever@eecs.umich.edu if kwargs: 1723101Sstever@eecs.umich.edu raise TypeError, 'extra unknown kwargs %s' % kwargs 1733101Sstever@eecs.umich.edu 1743101Sstever@eecs.umich.edu if not hasattr(self, 'desc'): 1753101Sstever@eecs.umich.edu raise TypeError, 'desc attribute missing' 1763101Sstever@eecs.umich.edu 1773101Sstever@eecs.umich.edu def __getattr__(self, attr): 1783101Sstever@eecs.umich.edu if attr == 'ptype': 1795033Smilesck@eecs.umich.edu ptype = SimObject.allClasses[self.ptype_str] 1806656Snate@binkert.org assert isSimObjectClass(ptype) 1815033Smilesck@eecs.umich.edu self.ptype = ptype 1825033Smilesck@eecs.umich.edu return ptype 1835033Smilesck@eecs.umich.edu 1843101Sstever@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 1853101Sstever@eecs.umich.edu (type(self).__name__, attr) 1863101Sstever@eecs.umich.edu 18710267SGeoffrey.Blake@arm.com def example_str(self): 18810267SGeoffrey.Blake@arm.com if hasattr(self.ptype, "ex_str"): 18910267SGeoffrey.Blake@arm.com return self.ptype.ex_str 19010267SGeoffrey.Blake@arm.com else: 19110267SGeoffrey.Blake@arm.com return self.ptype_str 19210267SGeoffrey.Blake@arm.com 19310267SGeoffrey.Blake@arm.com # Is the param available to be exposed on the command line 19410267SGeoffrey.Blake@arm.com def isCmdLineSettable(self): 19510267SGeoffrey.Blake@arm.com if hasattr(self.ptype, "cmd_line_settable"): 19610267SGeoffrey.Blake@arm.com return self.ptype.cmd_line_settable 19710267SGeoffrey.Blake@arm.com else: 19810267SGeoffrey.Blake@arm.com return False 19910267SGeoffrey.Blake@arm.com 2003101Sstever@eecs.umich.edu def convert(self, value): 2013101Sstever@eecs.umich.edu if isinstance(value, proxy.BaseProxy): 2023101Sstever@eecs.umich.edu value.set_param_desc(self) 2033101Sstever@eecs.umich.edu return value 2043101Sstever@eecs.umich.edu if not hasattr(self, 'ptype') and isNullPointer(value): 2053101Sstever@eecs.umich.edu # deferred evaluation of SimObject; continue to defer if 2063101Sstever@eecs.umich.edu # we're just assigning a null pointer 2073101Sstever@eecs.umich.edu return value 2083101Sstever@eecs.umich.edu if isinstance(value, self.ptype): 2093101Sstever@eecs.umich.edu return value 2103102Sstever@eecs.umich.edu if isNullPointer(value) and isSimObjectClass(self.ptype): 2113101Sstever@eecs.umich.edu return value 2123101Sstever@eecs.umich.edu return self.ptype(value) 2133101Sstever@eecs.umich.edu 21410267SGeoffrey.Blake@arm.com def pretty_print(self, value): 21510267SGeoffrey.Blake@arm.com if isinstance(value, proxy.BaseProxy): 21610267SGeoffrey.Blake@arm.com return str(value) 21710267SGeoffrey.Blake@arm.com if isNullPointer(value): 21810267SGeoffrey.Blake@arm.com return NULL 21910267SGeoffrey.Blake@arm.com return self.ptype(value).pretty_print(value) 22010267SGeoffrey.Blake@arm.com 2217673Snate@binkert.org def cxx_predecls(self, code): 2228607Sgblack@eecs.umich.edu code('#include <cstddef>') 2237673Snate@binkert.org self.ptype.cxx_predecls(code) 2243101Sstever@eecs.umich.edu 2257673Snate@binkert.org def swig_predecls(self, code): 2267673Snate@binkert.org self.ptype.swig_predecls(code) 2273101Sstever@eecs.umich.edu 2287673Snate@binkert.org def cxx_decl(self, code): 2297673Snate@binkert.org code('${{self.ptype.cxx_type}} ${{self.name}};') 2303101Sstever@eecs.umich.edu 2313101Sstever@eecs.umich.edu# Vector-valued parameter description. Just like ParamDesc, except 2323101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a 2333101Sstever@eecs.umich.edu# single value. 2343101Sstever@eecs.umich.edu 2353101Sstever@eecs.umich.educlass VectorParamValue(list): 2365033Smilesck@eecs.umich.edu __metaclass__ = MetaParamValue 2375475Snate@binkert.org def __setattr__(self, attr, value): 2385475Snate@binkert.org raise AttributeError, \ 2395475Snate@binkert.org "Not allowed to set %s on '%s'" % (attr, type(self).__name__) 2405475Snate@binkert.org 24110380SAndrew.Bardsley@arm.com def config_value(self): 24210380SAndrew.Bardsley@arm.com return [v.config_value() for v in self] 24310380SAndrew.Bardsley@arm.com 2443101Sstever@eecs.umich.edu def ini_str(self): 2453101Sstever@eecs.umich.edu return ' '.join([v.ini_str() for v in self]) 2463101Sstever@eecs.umich.edu 2474762Snate@binkert.org def getValue(self): 2484762Snate@binkert.org return [ v.getValue() for v in self ] 2494762Snate@binkert.org 2503101Sstever@eecs.umich.edu def unproxy(self, base): 2518460SAli.Saidi@ARM.com if len(self) == 1 and isinstance(self[0], proxy.AllProxy): 2528459SAli.Saidi@ARM.com return self[0].unproxy(base) 2538459SAli.Saidi@ARM.com else: 2548459SAli.Saidi@ARM.com return [v.unproxy(base) for v in self] 2553101Sstever@eecs.umich.edu 2567528Ssteve.reinhardt@amd.comclass SimObjectVector(VectorParamValue): 2577528Ssteve.reinhardt@amd.com # support clone operation 2587528Ssteve.reinhardt@amd.com def __call__(self, **kwargs): 2597528Ssteve.reinhardt@amd.com return SimObjectVector([v(**kwargs) for v in self]) 2607528Ssteve.reinhardt@amd.com 2617528Ssteve.reinhardt@amd.com def clear_parent(self, old_parent): 2623101Sstever@eecs.umich.edu for v in self: 2637528Ssteve.reinhardt@amd.com v.clear_parent(old_parent) 2647528Ssteve.reinhardt@amd.com 2657528Ssteve.reinhardt@amd.com def set_parent(self, parent, name): 2667528Ssteve.reinhardt@amd.com if len(self) == 1: 2677528Ssteve.reinhardt@amd.com self[0].set_parent(parent, name) 2687528Ssteve.reinhardt@amd.com else: 2697528Ssteve.reinhardt@amd.com width = int(math.ceil(math.log(len(self))/math.log(10))) 2707528Ssteve.reinhardt@amd.com for i,v in enumerate(self): 2717528Ssteve.reinhardt@amd.com v.set_parent(parent, "%s%0*d" % (name, width, i)) 2727528Ssteve.reinhardt@amd.com 2738321Ssteve.reinhardt@amd.com def has_parent(self): 2748321Ssteve.reinhardt@amd.com return reduce(lambda x,y: x and y, [v.has_parent() for v in self]) 2757528Ssteve.reinhardt@amd.com 2767528Ssteve.reinhardt@amd.com # return 'cpu0 cpu1' etc. for print_ini() 2777528Ssteve.reinhardt@amd.com def get_name(self): 2787528Ssteve.reinhardt@amd.com return ' '.join([v._name for v in self]) 2797528Ssteve.reinhardt@amd.com 2807528Ssteve.reinhardt@amd.com # By iterating through the constituent members of the vector here 2817528Ssteve.reinhardt@amd.com # we can nicely handle iterating over all a SimObject's children 2827528Ssteve.reinhardt@amd.com # without having to provide lots of special functions on 2837528Ssteve.reinhardt@amd.com # SimObjectVector directly. 2847528Ssteve.reinhardt@amd.com def descendants(self): 2857528Ssteve.reinhardt@amd.com for v in self: 2867528Ssteve.reinhardt@amd.com for obj in v.descendants(): 2877528Ssteve.reinhardt@amd.com yield obj 2883101Sstever@eecs.umich.edu 2898664SAli.Saidi@ARM.com def get_config_as_dict(self): 2908664SAli.Saidi@ARM.com a = [] 2918664SAli.Saidi@ARM.com for v in self: 2928664SAli.Saidi@ARM.com a.append(v.get_config_as_dict()) 2938664SAli.Saidi@ARM.com return a 2948664SAli.Saidi@ARM.com 2959953Sgeoffrey.blake@arm.com # If we are replacing an item in the vector, make sure to set the 2969953Sgeoffrey.blake@arm.com # parent reference of the new SimObject to be the same as the parent 2979953Sgeoffrey.blake@arm.com # of the SimObject being replaced. Useful to have if we created 2989953Sgeoffrey.blake@arm.com # a SimObjectVector of temporary objects that will be modified later in 2999953Sgeoffrey.blake@arm.com # configuration scripts. 3009953Sgeoffrey.blake@arm.com def __setitem__(self, key, value): 3019953Sgeoffrey.blake@arm.com val = self[key] 3029953Sgeoffrey.blake@arm.com if value.has_parent(): 3039953Sgeoffrey.blake@arm.com warn("SimObject %s already has a parent" % value.get_name() +\ 3049953Sgeoffrey.blake@arm.com " that is being overwritten by a SimObjectVector") 3059953Sgeoffrey.blake@arm.com value.set_parent(val.get_parent(), val._name) 3069953Sgeoffrey.blake@arm.com super(SimObjectVector, self).__setitem__(key, value) 3079953Sgeoffrey.blake@arm.com 30810267SGeoffrey.Blake@arm.com # Enumerate the params of each member of the SimObject vector. Creates 30910267SGeoffrey.Blake@arm.com # strings that will allow indexing into the vector by the python code and 31010267SGeoffrey.Blake@arm.com # allow it to be specified on the command line. 31110267SGeoffrey.Blake@arm.com def enumerateParams(self, flags_dict = {}, 31210267SGeoffrey.Blake@arm.com cmd_line_str = "", 31310267SGeoffrey.Blake@arm.com access_str = ""): 31410267SGeoffrey.Blake@arm.com if hasattr(self, "_paramEnumed"): 31510267SGeoffrey.Blake@arm.com print "Cycle detected enumerating params at %s?!" % (cmd_line_str) 31610267SGeoffrey.Blake@arm.com else: 31710267SGeoffrey.Blake@arm.com x = 0 31810267SGeoffrey.Blake@arm.com for vals in self: 31910267SGeoffrey.Blake@arm.com # Each entry in the SimObjectVector should be an 32010267SGeoffrey.Blake@arm.com # instance of a SimObject 32110267SGeoffrey.Blake@arm.com flags_dict = vals.enumerateParams(flags_dict, 32210267SGeoffrey.Blake@arm.com cmd_line_str + "%d." % x, 32310267SGeoffrey.Blake@arm.com access_str + "[%d]." % x) 32410267SGeoffrey.Blake@arm.com x = x + 1 32510267SGeoffrey.Blake@arm.com 32610267SGeoffrey.Blake@arm.com return flags_dict 32710267SGeoffrey.Blake@arm.com 3283101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc): 3293101Sstever@eecs.umich.edu # Convert assigned value to appropriate type. If the RHS is not a 3303101Sstever@eecs.umich.edu # list or tuple, it generates a single-element list. 3313101Sstever@eecs.umich.edu def convert(self, value): 3323101Sstever@eecs.umich.edu if isinstance(value, (list, tuple)): 3333101Sstever@eecs.umich.edu # list: coerce each element into new list 3343101Sstever@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) for v in value ] 33510364SGeoffrey.Blake@arm.com elif isinstance(value, str): 33610364SGeoffrey.Blake@arm.com # If input is a csv string 33710364SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) \ 33810364SGeoffrey.Blake@arm.com for v in value.strip('[').strip(']').split(',') ] 3393101Sstever@eecs.umich.edu else: 3404762Snate@binkert.org # singleton: coerce to a single-element list 3414762Snate@binkert.org tmp_list = [ ParamDesc.convert(self, value) ] 3424762Snate@binkert.org 3434762Snate@binkert.org if isSimObjectSequence(tmp_list): 3447528Ssteve.reinhardt@amd.com return SimObjectVector(tmp_list) 3454762Snate@binkert.org else: 3464762Snate@binkert.org return VectorParamValue(tmp_list) 3474762Snate@binkert.org 34810267SGeoffrey.Blake@arm.com # Produce a human readable example string that describes 34910267SGeoffrey.Blake@arm.com # how to set this vector parameter in the absence of a default 35010267SGeoffrey.Blake@arm.com # value. 35110267SGeoffrey.Blake@arm.com def example_str(self): 35210267SGeoffrey.Blake@arm.com s = super(VectorParamDesc, self).example_str() 35310267SGeoffrey.Blake@arm.com help_str = "[" + s + "," + s + ", ...]" 35410267SGeoffrey.Blake@arm.com return help_str 35510267SGeoffrey.Blake@arm.com 35610267SGeoffrey.Blake@arm.com # Produce a human readable representation of the value of this vector param. 35710267SGeoffrey.Blake@arm.com def pretty_print(self, value): 35810267SGeoffrey.Blake@arm.com if isinstance(value, (list, tuple)): 35910267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ] 36010267SGeoffrey.Blake@arm.com elif isinstance(value, str): 36110267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ] 36210267SGeoffrey.Blake@arm.com else: 36310267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, value) ] 36410267SGeoffrey.Blake@arm.com 36510267SGeoffrey.Blake@arm.com return tmp_list 36610267SGeoffrey.Blake@arm.com 36710267SGeoffrey.Blake@arm.com # This is a helper function for the new config system 36810267SGeoffrey.Blake@arm.com def __call__(self, value): 36910267SGeoffrey.Blake@arm.com if isinstance(value, (list, tuple)): 37010267SGeoffrey.Blake@arm.com # list: coerce each element into new list 37110267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) for v in value ] 37210267SGeoffrey.Blake@arm.com elif isinstance(value, str): 37310267SGeoffrey.Blake@arm.com # If input is a csv string 37410364SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) \ 37510364SGeoffrey.Blake@arm.com for v in value.strip('[').strip(']').split(',') ] 37610267SGeoffrey.Blake@arm.com else: 37710267SGeoffrey.Blake@arm.com # singleton: coerce to a single-element list 37810267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, value) ] 37910267SGeoffrey.Blake@arm.com 38010267SGeoffrey.Blake@arm.com return VectorParamValue(tmp_list) 38110267SGeoffrey.Blake@arm.com 3828596Ssteve.reinhardt@amd.com def swig_module_name(self): 3838596Ssteve.reinhardt@amd.com return "%s_vector" % self.ptype_str 3848596Ssteve.reinhardt@amd.com 3857673Snate@binkert.org def swig_predecls(self, code): 3868596Ssteve.reinhardt@amd.com code('%import "${{self.swig_module_name()}}.i"') 3874762Snate@binkert.org 3887673Snate@binkert.org def swig_decl(self, code): 38911802Sandreas.sandberg@arm.com code('%module(package="_m5") ${{self.swig_module_name()}}') 3907675Snate@binkert.org code('%{') 3917675Snate@binkert.org self.ptype.cxx_predecls(code) 3927675Snate@binkert.org code('%}') 3937675Snate@binkert.org code() 3948656Sandreas.hansson@arm.com # Make sure the SWIGPY_SLICE_ARG is defined through this inclusion 3958656Sandreas.hansson@arm.com code('%include "std_container.i"') 3968656Sandreas.hansson@arm.com code() 3977675Snate@binkert.org self.ptype.swig_predecls(code) 3987675Snate@binkert.org code() 3997673Snate@binkert.org code('%include "std_vector.i"') 4007675Snate@binkert.org code() 4017675Snate@binkert.org 4027675Snate@binkert.org ptype = self.ptype_str 4037675Snate@binkert.org cxx_type = self.ptype.cxx_type 4047675Snate@binkert.org 4057675Snate@binkert.org code('%template(vector_$ptype) std::vector< $cxx_type >;') 4067675Snate@binkert.org 4077673Snate@binkert.org def cxx_predecls(self, code): 4087673Snate@binkert.org code('#include <vector>') 4097673Snate@binkert.org self.ptype.cxx_predecls(code) 4103101Sstever@eecs.umich.edu 4117673Snate@binkert.org def cxx_decl(self, code): 4127673Snate@binkert.org code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};') 4133101Sstever@eecs.umich.edu 4143101Sstever@eecs.umich.educlass ParamFactory(object): 4153101Sstever@eecs.umich.edu def __init__(self, param_desc_class, ptype_str = None): 4163101Sstever@eecs.umich.edu self.param_desc_class = param_desc_class 4173101Sstever@eecs.umich.edu self.ptype_str = ptype_str 4183101Sstever@eecs.umich.edu 4193101Sstever@eecs.umich.edu def __getattr__(self, attr): 4203101Sstever@eecs.umich.edu if self.ptype_str: 4213101Sstever@eecs.umich.edu attr = self.ptype_str + '.' + attr 4223101Sstever@eecs.umich.edu return ParamFactory(self.param_desc_class, attr) 4233101Sstever@eecs.umich.edu 4243101Sstever@eecs.umich.edu # E.g., Param.Int(5, "number of widgets") 4253101Sstever@eecs.umich.edu def __call__(self, *args, **kwargs): 4263101Sstever@eecs.umich.edu ptype = None 4273101Sstever@eecs.umich.edu try: 4285033Smilesck@eecs.umich.edu ptype = allParams[self.ptype_str] 4295033Smilesck@eecs.umich.edu except KeyError: 4303101Sstever@eecs.umich.edu # if name isn't defined yet, assume it's a SimObject, and 4313101Sstever@eecs.umich.edu # try to resolve it later 4323101Sstever@eecs.umich.edu pass 4333101Sstever@eecs.umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 4343101Sstever@eecs.umich.edu 4353101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc) 4363101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc) 4373101Sstever@eecs.umich.edu 4383101Sstever@eecs.umich.edu##################################################################### 4393101Sstever@eecs.umich.edu# 4403101Sstever@eecs.umich.edu# Parameter Types 4413101Sstever@eecs.umich.edu# 4423101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types 4433101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more 4443101Sstever@eecs.umich.edu# flexible to define our own set of types. This gives us more control 4453101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the 4463101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via 4473101Sstever@eecs.umich.edu# the __str__() conversion method). 4483101Sstever@eecs.umich.edu# 4493101Sstever@eecs.umich.edu##################################################################### 4503101Sstever@eecs.umich.edu 4513101Sstever@eecs.umich.edu# String-valued parameter. Just mixin the ParamValue class with the 4523101Sstever@eecs.umich.edu# built-in str class. 4533101Sstever@eecs.umich.educlass String(ParamValue,str): 4543101Sstever@eecs.umich.edu cxx_type = 'std::string' 45510267SGeoffrey.Blake@arm.com cmd_line_settable = True 4567673Snate@binkert.org 4577673Snate@binkert.org @classmethod 4587673Snate@binkert.org def cxx_predecls(self, code): 4597673Snate@binkert.org code('#include <string>') 4607673Snate@binkert.org 4617673Snate@binkert.org @classmethod 4627673Snate@binkert.org def swig_predecls(cls, code): 4637673Snate@binkert.org code('%include "std_string.i"') 4644762Snate@binkert.org 46510267SGeoffrey.Blake@arm.com def __call__(self, value): 46610267SGeoffrey.Blake@arm.com self = value 46710267SGeoffrey.Blake@arm.com return value 46810267SGeoffrey.Blake@arm.com 46910458Sandreas.hansson@arm.com @classmethod 47010458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 47110458Sandreas.hansson@arm.com code('%s = %s;' % (dest, src)) 47210458Sandreas.hansson@arm.com code('%s true;' % ret) 47310458Sandreas.hansson@arm.com 4744762Snate@binkert.org def getValue(self): 4754762Snate@binkert.org return self 4763101Sstever@eecs.umich.edu 4773101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math 4783101Sstever@eecs.umich.edu# operations in a type-safe way. e.g., a Latency times an int returns 4793101Sstever@eecs.umich.edu# a new Latency object. 4803101Sstever@eecs.umich.educlass NumericParamValue(ParamValue): 4813101Sstever@eecs.umich.edu def __str__(self): 4823101Sstever@eecs.umich.edu return str(self.value) 4833101Sstever@eecs.umich.edu 4843101Sstever@eecs.umich.edu def __float__(self): 4853101Sstever@eecs.umich.edu return float(self.value) 4863101Sstever@eecs.umich.edu 4873714Sstever@eecs.umich.edu def __long__(self): 4883714Sstever@eecs.umich.edu return long(self.value) 4893714Sstever@eecs.umich.edu 4903714Sstever@eecs.umich.edu def __int__(self): 4913714Sstever@eecs.umich.edu return int(self.value) 4923714Sstever@eecs.umich.edu 4933101Sstever@eecs.umich.edu # hook for bounds checking 4943101Sstever@eecs.umich.edu def _check(self): 4953101Sstever@eecs.umich.edu return 4963101Sstever@eecs.umich.edu 4973101Sstever@eecs.umich.edu def __mul__(self, other): 4983101Sstever@eecs.umich.edu newobj = self.__class__(self) 4993101Sstever@eecs.umich.edu newobj.value *= other 5003101Sstever@eecs.umich.edu newobj._check() 5013101Sstever@eecs.umich.edu return newobj 5023101Sstever@eecs.umich.edu 5033101Sstever@eecs.umich.edu __rmul__ = __mul__ 5043101Sstever@eecs.umich.edu 5053101Sstever@eecs.umich.edu def __div__(self, other): 5063101Sstever@eecs.umich.edu newobj = self.__class__(self) 5073101Sstever@eecs.umich.edu newobj.value /= other 5083101Sstever@eecs.umich.edu newobj._check() 5093101Sstever@eecs.umich.edu return newobj 5103101Sstever@eecs.umich.edu 5113101Sstever@eecs.umich.edu def __sub__(self, other): 5123101Sstever@eecs.umich.edu newobj = self.__class__(self) 5133101Sstever@eecs.umich.edu newobj.value -= other 5143101Sstever@eecs.umich.edu newobj._check() 5153101Sstever@eecs.umich.edu return newobj 5163101Sstever@eecs.umich.edu 51710380SAndrew.Bardsley@arm.com def config_value(self): 51810380SAndrew.Bardsley@arm.com return self.value 51910380SAndrew.Bardsley@arm.com 52010458Sandreas.hansson@arm.com @classmethod 52110458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 52210458Sandreas.hansson@arm.com # Assume that base/str.hh will be included anyway 52310458Sandreas.hansson@arm.com # code('#include "base/str.hh"') 52410458Sandreas.hansson@arm.com pass 52510458Sandreas.hansson@arm.com 52610458Sandreas.hansson@arm.com # The default for parsing PODs from an .ini entry is to extract from an 52710458Sandreas.hansson@arm.com # istringstream and let overloading choose the right type according to 52810458Sandreas.hansson@arm.com # the dest type. 52910458Sandreas.hansson@arm.com @classmethod 53010458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 53110458Sandreas.hansson@arm.com code('%s to_number(%s, %s);' % (ret, src, dest)) 53210458Sandreas.hansson@arm.com 5333101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters. See CheckedInt. 5345033Smilesck@eecs.umich.educlass CheckedIntType(MetaParamValue): 5353101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 5363101Sstever@eecs.umich.edu super(CheckedIntType, cls).__init__(name, bases, dict) 5373101Sstever@eecs.umich.edu 5383101Sstever@eecs.umich.edu # CheckedInt is an abstract base class, so we actually don't 5393101Sstever@eecs.umich.edu # want to do any processing on it... the rest of this code is 5403101Sstever@eecs.umich.edu # just for classes that derive from CheckedInt. 5413101Sstever@eecs.umich.edu if name == 'CheckedInt': 5423101Sstever@eecs.umich.edu return 5433101Sstever@eecs.umich.edu 5443101Sstever@eecs.umich.edu if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 5453101Sstever@eecs.umich.edu if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 5463101Sstever@eecs.umich.edu panic("CheckedInt subclass %s must define either\n" \ 5475822Ssaidi@eecs.umich.edu " 'min' and 'max' or 'size' and 'unsigned'\n", 5485822Ssaidi@eecs.umich.edu name); 5493101Sstever@eecs.umich.edu if cls.unsigned: 5503101Sstever@eecs.umich.edu cls.min = 0 5513101Sstever@eecs.umich.edu cls.max = 2 ** cls.size - 1 5523101Sstever@eecs.umich.edu else: 5533101Sstever@eecs.umich.edu cls.min = -(2 ** (cls.size - 1)) 5543101Sstever@eecs.umich.edu cls.max = (2 ** (cls.size - 1)) - 1 5553101Sstever@eecs.umich.edu 5563101Sstever@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters. This 5573101Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific 5583101Sstever@eecs.umich.edu# bounds. Initialization of the min and max bounds is done in the 5593101Sstever@eecs.umich.edu# metaclass CheckedIntType.__init__. 5603101Sstever@eecs.umich.educlass CheckedInt(NumericParamValue): 5613101Sstever@eecs.umich.edu __metaclass__ = CheckedIntType 56210267SGeoffrey.Blake@arm.com cmd_line_settable = True 5633101Sstever@eecs.umich.edu 5643101Sstever@eecs.umich.edu def _check(self): 5653101Sstever@eecs.umich.edu if not self.min <= self.value <= self.max: 5663101Sstever@eecs.umich.edu raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 5673101Sstever@eecs.umich.edu (self.min, self.value, self.max) 5683101Sstever@eecs.umich.edu 5693101Sstever@eecs.umich.edu def __init__(self, value): 5703101Sstever@eecs.umich.edu if isinstance(value, str): 5713102Sstever@eecs.umich.edu self.value = convert.toInteger(value) 5723714Sstever@eecs.umich.edu elif isinstance(value, (int, long, float, NumericParamValue)): 5733101Sstever@eecs.umich.edu self.value = long(value) 5743714Sstever@eecs.umich.edu else: 5753714Sstever@eecs.umich.edu raise TypeError, "Can't convert object of type %s to CheckedInt" \ 5763714Sstever@eecs.umich.edu % type(value).__name__ 5773101Sstever@eecs.umich.edu self._check() 5783101Sstever@eecs.umich.edu 57910267SGeoffrey.Blake@arm.com def __call__(self, value): 58010267SGeoffrey.Blake@arm.com self.__init__(value) 58110267SGeoffrey.Blake@arm.com return value 58210267SGeoffrey.Blake@arm.com 5837673Snate@binkert.org @classmethod 5847673Snate@binkert.org def cxx_predecls(cls, code): 5857673Snate@binkert.org # most derived types require this, so we just do it here once 5867673Snate@binkert.org code('#include "base/types.hh"') 5877673Snate@binkert.org 5887673Snate@binkert.org @classmethod 5897673Snate@binkert.org def swig_predecls(cls, code): 5907673Snate@binkert.org # most derived types require this, so we just do it here once 5917673Snate@binkert.org code('%import "stdint.i"') 5927673Snate@binkert.org code('%import "base/types.hh"') 5937673Snate@binkert.org 5944762Snate@binkert.org def getValue(self): 5954762Snate@binkert.org return long(self.value) 5964762Snate@binkert.org 5973101Sstever@eecs.umich.educlass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 5983101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 5993101Sstever@eecs.umich.edu 6003101Sstever@eecs.umich.educlass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 6013101Sstever@eecs.umich.educlass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 6023101Sstever@eecs.umich.educlass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 6033101Sstever@eecs.umich.educlass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 6043101Sstever@eecs.umich.educlass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 6053101Sstever@eecs.umich.educlass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 6063101Sstever@eecs.umich.educlass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 6073101Sstever@eecs.umich.educlass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 6083101Sstever@eecs.umich.edu 6093101Sstever@eecs.umich.educlass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 6103101Sstever@eecs.umich.educlass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 6113101Sstever@eecs.umich.educlass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 6123101Sstever@eecs.umich.educlass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 6133101Sstever@eecs.umich.edu 6143101Sstever@eecs.umich.educlass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 6153101Sstever@eecs.umich.edu 6169184Sandreas.hansson@arm.comclass Cycles(CheckedInt): 6179184Sandreas.hansson@arm.com cxx_type = 'Cycles' 6189184Sandreas.hansson@arm.com size = 64 6199184Sandreas.hansson@arm.com unsigned = True 6209184Sandreas.hansson@arm.com 6219184Sandreas.hansson@arm.com def getValue(self): 62211802Sandreas.sandberg@arm.com from _m5.core import Cycles 6239184Sandreas.hansson@arm.com return Cycles(self.value) 6249184Sandreas.hansson@arm.com 62510458Sandreas.hansson@arm.com @classmethod 62610458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 62710458Sandreas.hansson@arm.com # Assume that base/str.hh will be included anyway 62810458Sandreas.hansson@arm.com # code('#include "base/str.hh"') 62910458Sandreas.hansson@arm.com pass 63010458Sandreas.hansson@arm.com 63110458Sandreas.hansson@arm.com @classmethod 63210458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 63310458Sandreas.hansson@arm.com code('uint64_t _temp;') 63410458Sandreas.hansson@arm.com code('bool _ret = to_number(%s, _temp);' % src) 63510458Sandreas.hansson@arm.com code('if (_ret)') 63610458Sandreas.hansson@arm.com code(' %s = Cycles(_temp);' % dest) 63710458Sandreas.hansson@arm.com code('%s _ret;' % ret) 63810458Sandreas.hansson@arm.com 6393101Sstever@eecs.umich.educlass Float(ParamValue, float): 6404446Sbinkertn@umich.edu cxx_type = 'double' 64110668SGeoffrey.Blake@arm.com cmd_line_settable = True 6423101Sstever@eecs.umich.edu 6435468Snate@binkert.org def __init__(self, value): 64410267SGeoffrey.Blake@arm.com if isinstance(value, (int, long, float, NumericParamValue, Float, str)): 6455468Snate@binkert.org self.value = float(value) 6465468Snate@binkert.org else: 6475468Snate@binkert.org raise TypeError, "Can't convert object of type %s to Float" \ 6485468Snate@binkert.org % type(value).__name__ 6495468Snate@binkert.org 65010267SGeoffrey.Blake@arm.com def __call__(self, value): 65110267SGeoffrey.Blake@arm.com self.__init__(value) 65210267SGeoffrey.Blake@arm.com return value 65310267SGeoffrey.Blake@arm.com 6544762Snate@binkert.org def getValue(self): 6554762Snate@binkert.org return float(self.value) 6564762Snate@binkert.org 65710380SAndrew.Bardsley@arm.com def config_value(self): 65810380SAndrew.Bardsley@arm.com return self 65910380SAndrew.Bardsley@arm.com 66010458Sandreas.hansson@arm.com @classmethod 66110458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 66210458Sandreas.hansson@arm.com code('#include <sstream>') 66310458Sandreas.hansson@arm.com 66410458Sandreas.hansson@arm.com @classmethod 66510458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 66610458Sandreas.hansson@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 66710458Sandreas.hansson@arm.com 6683101Sstever@eecs.umich.educlass MemorySize(CheckedInt): 6693101Sstever@eecs.umich.edu cxx_type = 'uint64_t' 67010267SGeoffrey.Blake@arm.com ex_str = '512MB' 6713101Sstever@eecs.umich.edu size = 64 6723101Sstever@eecs.umich.edu unsigned = True 6733101Sstever@eecs.umich.edu def __init__(self, value): 6743101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 6753101Sstever@eecs.umich.edu self.value = value.value 6763101Sstever@eecs.umich.edu else: 6773102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 6783101Sstever@eecs.umich.edu self._check() 6793101Sstever@eecs.umich.edu 6803101Sstever@eecs.umich.educlass MemorySize32(CheckedInt): 6814168Sbinkertn@umich.edu cxx_type = 'uint32_t' 68210267SGeoffrey.Blake@arm.com ex_str = '512MB' 6833101Sstever@eecs.umich.edu size = 32 6843101Sstever@eecs.umich.edu unsigned = True 6853101Sstever@eecs.umich.edu def __init__(self, value): 6863101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 6873101Sstever@eecs.umich.edu self.value = value.value 6883101Sstever@eecs.umich.edu else: 6893102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 6903101Sstever@eecs.umich.edu self._check() 6913101Sstever@eecs.umich.edu 6923101Sstever@eecs.umich.educlass Addr(CheckedInt): 6933101Sstever@eecs.umich.edu cxx_type = 'Addr' 6943101Sstever@eecs.umich.edu size = 64 6953101Sstever@eecs.umich.edu unsigned = True 6963101Sstever@eecs.umich.edu def __init__(self, value): 6973101Sstever@eecs.umich.edu if isinstance(value, Addr): 6983101Sstever@eecs.umich.edu self.value = value.value 6993101Sstever@eecs.umich.edu else: 7003101Sstever@eecs.umich.edu try: 70110317Smitch.hayenga@arm.com # Often addresses are referred to with sizes. Ex: A device 70210317Smitch.hayenga@arm.com # base address is at "512MB". Use toMemorySize() to convert 70310317Smitch.hayenga@arm.com # these into addresses. If the address is not specified with a 70410317Smitch.hayenga@arm.com # "size", an exception will occur and numeric translation will 70510317Smitch.hayenga@arm.com # proceed below. 7063102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 70710317Smitch.hayenga@arm.com except (TypeError, ValueError): 70810317Smitch.hayenga@arm.com # Convert number to string and use long() to do automatic 70910317Smitch.hayenga@arm.com # base conversion (requires base=0 for auto-conversion) 71010317Smitch.hayenga@arm.com self.value = long(str(value), base=0) 71110317Smitch.hayenga@arm.com 7123101Sstever@eecs.umich.edu self._check() 7133584Ssaidi@eecs.umich.edu def __add__(self, other): 7143584Ssaidi@eecs.umich.edu if isinstance(other, Addr): 7153584Ssaidi@eecs.umich.edu return self.value + other.value 7163584Ssaidi@eecs.umich.edu else: 7173584Ssaidi@eecs.umich.edu return self.value + other 71810267SGeoffrey.Blake@arm.com def pretty_print(self, value): 71910267SGeoffrey.Blake@arm.com try: 72010267SGeoffrey.Blake@arm.com val = convert.toMemorySize(value) 72110267SGeoffrey.Blake@arm.com except TypeError: 72210267SGeoffrey.Blake@arm.com val = long(value) 72310267SGeoffrey.Blake@arm.com return "0x%x" % long(val) 7243101Sstever@eecs.umich.edu 7259232Sandreas.hansson@arm.comclass AddrRange(ParamValue): 7269235Sandreas.hansson@arm.com cxx_type = 'AddrRange' 7273101Sstever@eecs.umich.edu 7283101Sstever@eecs.umich.edu def __init__(self, *args, **kwargs): 72910676Sandreas.hansson@arm.com # Disable interleaving and hashing by default 7309411Sandreas.hansson@arm.com self.intlvHighBit = 0 73110676Sandreas.hansson@arm.com self.xorHighBit = 0 7329411Sandreas.hansson@arm.com self.intlvBits = 0 7339411Sandreas.hansson@arm.com self.intlvMatch = 0 7349411Sandreas.hansson@arm.com 7353101Sstever@eecs.umich.edu def handle_kwargs(self, kwargs): 7369411Sandreas.hansson@arm.com # An address range needs to have an upper limit, specified 7379411Sandreas.hansson@arm.com # either explicitly with an end, or as an offset using the 7389411Sandreas.hansson@arm.com # size keyword. 7393101Sstever@eecs.umich.edu if 'end' in kwargs: 7409232Sandreas.hansson@arm.com self.end = Addr(kwargs.pop('end')) 7413101Sstever@eecs.umich.edu elif 'size' in kwargs: 7429232Sandreas.hansson@arm.com self.end = self.start + Addr(kwargs.pop('size')) - 1 7433101Sstever@eecs.umich.edu else: 7443101Sstever@eecs.umich.edu raise TypeError, "Either end or size must be specified" 7453101Sstever@eecs.umich.edu 7469411Sandreas.hansson@arm.com # Now on to the optional bit 7479411Sandreas.hansson@arm.com if 'intlvHighBit' in kwargs: 7489411Sandreas.hansson@arm.com self.intlvHighBit = int(kwargs.pop('intlvHighBit')) 74910676Sandreas.hansson@arm.com if 'xorHighBit' in kwargs: 75010676Sandreas.hansson@arm.com self.xorHighBit = int(kwargs.pop('xorHighBit')) 7519411Sandreas.hansson@arm.com if 'intlvBits' in kwargs: 7529411Sandreas.hansson@arm.com self.intlvBits = int(kwargs.pop('intlvBits')) 7539411Sandreas.hansson@arm.com if 'intlvMatch' in kwargs: 7549411Sandreas.hansson@arm.com self.intlvMatch = int(kwargs.pop('intlvMatch')) 7559411Sandreas.hansson@arm.com 7563101Sstever@eecs.umich.edu if len(args) == 0: 7579232Sandreas.hansson@arm.com self.start = Addr(kwargs.pop('start')) 7583101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 7593101Sstever@eecs.umich.edu 7603101Sstever@eecs.umich.edu elif len(args) == 1: 7613101Sstever@eecs.umich.edu if kwargs: 7629232Sandreas.hansson@arm.com self.start = Addr(args[0]) 7633101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 7645219Ssaidi@eecs.umich.edu elif isinstance(args[0], (list, tuple)): 7659232Sandreas.hansson@arm.com self.start = Addr(args[0][0]) 7669232Sandreas.hansson@arm.com self.end = Addr(args[0][1]) 7673101Sstever@eecs.umich.edu else: 7689232Sandreas.hansson@arm.com self.start = Addr(0) 7699232Sandreas.hansson@arm.com self.end = Addr(args[0]) - 1 7703101Sstever@eecs.umich.edu 7713101Sstever@eecs.umich.edu elif len(args) == 2: 7729232Sandreas.hansson@arm.com self.start = Addr(args[0]) 7739232Sandreas.hansson@arm.com self.end = Addr(args[1]) 7743101Sstever@eecs.umich.edu else: 7753101Sstever@eecs.umich.edu raise TypeError, "Too many arguments specified" 7763101Sstever@eecs.umich.edu 7773101Sstever@eecs.umich.edu if kwargs: 7789232Sandreas.hansson@arm.com raise TypeError, "Too many keywords: %s" % kwargs.keys() 7793101Sstever@eecs.umich.edu 7803101Sstever@eecs.umich.edu def __str__(self): 78111620SMatthew.Poremba@amd.com return '%s:%s:%s:%s:%s:%s' \ 78211620SMatthew.Poremba@amd.com % (self.start, self.end, self.intlvHighBit, self.xorHighBit,\ 78311620SMatthew.Poremba@amd.com self.intlvBits, self.intlvMatch) 7849232Sandreas.hansson@arm.com 7859232Sandreas.hansson@arm.com def size(self): 7869411Sandreas.hansson@arm.com # Divide the size by the size of the interleaving slice 7879411Sandreas.hansson@arm.com return (long(self.end) - long(self.start) + 1) >> self.intlvBits 7883101Sstever@eecs.umich.edu 7897673Snate@binkert.org @classmethod 7907673Snate@binkert.org def cxx_predecls(cls, code): 7919232Sandreas.hansson@arm.com Addr.cxx_predecls(code) 7929235Sandreas.hansson@arm.com code('#include "base/addr_range.hh"') 7937675Snate@binkert.org 7947675Snate@binkert.org @classmethod 7957675Snate@binkert.org def swig_predecls(cls, code): 7969232Sandreas.hansson@arm.com Addr.swig_predecls(code) 7977673Snate@binkert.org 79810458Sandreas.hansson@arm.com @classmethod 79910458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 80010458Sandreas.hansson@arm.com code('#include <sstream>') 80110458Sandreas.hansson@arm.com 80210458Sandreas.hansson@arm.com @classmethod 80310458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 80411620SMatthew.Poremba@amd.com code('uint64_t _start, _end, _intlvHighBit = 0, _xorHighBit = 0;') 80511620SMatthew.Poremba@amd.com code('uint64_t _intlvBits = 0, _intlvMatch = 0;') 80610458Sandreas.hansson@arm.com code('char _sep;') 80710458Sandreas.hansson@arm.com code('std::istringstream _stream(${src});') 80810458Sandreas.hansson@arm.com code('_stream >> _start;') 80910458Sandreas.hansson@arm.com code('_stream.get(_sep);') 81010458Sandreas.hansson@arm.com code('_stream >> _end;') 81111620SMatthew.Poremba@amd.com code('if (!_stream.fail() && !_stream.eof()) {') 81211620SMatthew.Poremba@amd.com code(' _stream.get(_sep);') 81311620SMatthew.Poremba@amd.com code(' _stream >> _intlvHighBit;') 81411620SMatthew.Poremba@amd.com code(' _stream.get(_sep);') 81511620SMatthew.Poremba@amd.com code(' _stream >> _xorHighBit;') 81611620SMatthew.Poremba@amd.com code(' _stream.get(_sep);') 81711620SMatthew.Poremba@amd.com code(' _stream >> _intlvBits;') 81811620SMatthew.Poremba@amd.com code(' _stream.get(_sep);') 81911620SMatthew.Poremba@amd.com code(' _stream >> _intlvMatch;') 82011620SMatthew.Poremba@amd.com code('}') 82110458Sandreas.hansson@arm.com code('bool _ret = !_stream.fail() &&' 82210458Sandreas.hansson@arm.com '_stream.eof() && _sep == \':\';') 82310458Sandreas.hansson@arm.com code('if (_ret)') 82411620SMatthew.Poremba@amd.com code(' ${dest} = AddrRange(_start, _end, _intlvHighBit, \ 82511620SMatthew.Poremba@amd.com _xorHighBit, _intlvBits, _intlvMatch);') 82610458Sandreas.hansson@arm.com code('${ret} _ret;') 82710458Sandreas.hansson@arm.com 8284762Snate@binkert.org def getValue(self): 8299235Sandreas.hansson@arm.com # Go from the Python class to the wrapped C++ class generated 8309235Sandreas.hansson@arm.com # by swig 83111802Sandreas.sandberg@arm.com from _m5.range import AddrRange 8324762Snate@binkert.org 8339411Sandreas.hansson@arm.com return AddrRange(long(self.start), long(self.end), 83410676Sandreas.hansson@arm.com int(self.intlvHighBit), int(self.xorHighBit), 83510676Sandreas.hansson@arm.com int(self.intlvBits), int(self.intlvMatch)) 8363101Sstever@eecs.umich.edu 8373101Sstever@eecs.umich.edu# Boolean parameter type. Python doesn't let you subclass bool, since 8383101Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and 8393101Sstever@eecs.umich.edu# False. Thus this is a little more complicated than String. 8403101Sstever@eecs.umich.educlass Bool(ParamValue): 8413101Sstever@eecs.umich.edu cxx_type = 'bool' 84210267SGeoffrey.Blake@arm.com cmd_line_settable = True 84310267SGeoffrey.Blake@arm.com 8443101Sstever@eecs.umich.edu def __init__(self, value): 8453101Sstever@eecs.umich.edu try: 8463102Sstever@eecs.umich.edu self.value = convert.toBool(value) 8473101Sstever@eecs.umich.edu except TypeError: 8483101Sstever@eecs.umich.edu self.value = bool(value) 8493101Sstever@eecs.umich.edu 85010267SGeoffrey.Blake@arm.com def __call__(self, value): 85110267SGeoffrey.Blake@arm.com self.__init__(value) 85210267SGeoffrey.Blake@arm.com return value 85310267SGeoffrey.Blake@arm.com 8544762Snate@binkert.org def getValue(self): 8554762Snate@binkert.org return bool(self.value) 8564762Snate@binkert.org 8573101Sstever@eecs.umich.edu def __str__(self): 8583101Sstever@eecs.umich.edu return str(self.value) 8593101Sstever@eecs.umich.edu 8608934SBrad.Beckmann@amd.com # implement truth value testing for Bool parameters so that these params 8618934SBrad.Beckmann@amd.com # evaluate correctly during the python configuration phase 8628934SBrad.Beckmann@amd.com def __nonzero__(self): 8638934SBrad.Beckmann@amd.com return bool(self.value) 8648934SBrad.Beckmann@amd.com 8653101Sstever@eecs.umich.edu def ini_str(self): 8663101Sstever@eecs.umich.edu if self.value: 8673101Sstever@eecs.umich.edu return 'true' 8683101Sstever@eecs.umich.edu return 'false' 8693101Sstever@eecs.umich.edu 87010380SAndrew.Bardsley@arm.com def config_value(self): 87110380SAndrew.Bardsley@arm.com return self.value 87210380SAndrew.Bardsley@arm.com 87310458Sandreas.hansson@arm.com @classmethod 87410458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 87510458Sandreas.hansson@arm.com # Assume that base/str.hh will be included anyway 87610458Sandreas.hansson@arm.com # code('#include "base/str.hh"') 87710458Sandreas.hansson@arm.com pass 87810458Sandreas.hansson@arm.com 87910458Sandreas.hansson@arm.com @classmethod 88010458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 88110458Sandreas.hansson@arm.com code('%s to_bool(%s, %s);' % (ret, src, dest)) 88210458Sandreas.hansson@arm.com 8833101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1): 8843101Sstever@eecs.umich.edu bytes = map(lambda x: int(x, 16), addr.split(':')) 8853101Sstever@eecs.umich.edu bytes[5] += val 8863101Sstever@eecs.umich.edu for i in (5, 4, 3, 2, 1): 8873101Sstever@eecs.umich.edu val,rem = divmod(bytes[i], 256) 8883101Sstever@eecs.umich.edu bytes[i] = rem 8893101Sstever@eecs.umich.edu if val == 0: 8903101Sstever@eecs.umich.edu break 8913101Sstever@eecs.umich.edu bytes[i - 1] += val 8923101Sstever@eecs.umich.edu assert(bytes[0] <= 255) 8933101Sstever@eecs.umich.edu return ':'.join(map(lambda x: '%02x' % x, bytes)) 8943101Sstever@eecs.umich.edu 8954380Sbinkertn@umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 8964380Sbinkertn@umich.edudef NextEthernetAddr(): 8974380Sbinkertn@umich.edu global _NextEthernetAddr 8983101Sstever@eecs.umich.edu 8994380Sbinkertn@umich.edu value = _NextEthernetAddr 9004380Sbinkertn@umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 9014380Sbinkertn@umich.edu return value 9023101Sstever@eecs.umich.edu 9033101Sstever@eecs.umich.educlass EthernetAddr(ParamValue): 9043101Sstever@eecs.umich.edu cxx_type = 'Net::EthAddr' 90510267SGeoffrey.Blake@arm.com ex_str = "00:90:00:00:00:01" 90610267SGeoffrey.Blake@arm.com cmd_line_settable = True 9077673Snate@binkert.org 9087673Snate@binkert.org @classmethod 9097673Snate@binkert.org def cxx_predecls(cls, code): 9107673Snate@binkert.org code('#include "base/inet.hh"') 9117673Snate@binkert.org 9127673Snate@binkert.org @classmethod 9137673Snate@binkert.org def swig_predecls(cls, code): 9147673Snate@binkert.org code('%include "python/swig/inet.i"') 9157673Snate@binkert.org 9163101Sstever@eecs.umich.edu def __init__(self, value): 9173101Sstever@eecs.umich.edu if value == NextEthernetAddr: 9183101Sstever@eecs.umich.edu self.value = value 9193101Sstever@eecs.umich.edu return 9203101Sstever@eecs.umich.edu 9213101Sstever@eecs.umich.edu if not isinstance(value, str): 9223101Sstever@eecs.umich.edu raise TypeError, "expected an ethernet address and didn't get one" 9233101Sstever@eecs.umich.edu 9243101Sstever@eecs.umich.edu bytes = value.split(':') 9253101Sstever@eecs.umich.edu if len(bytes) != 6: 9263101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 9273101Sstever@eecs.umich.edu 9283101Sstever@eecs.umich.edu for byte in bytes: 9299941SGeoffrey.Blake@arm.com if not 0 <= int(byte, base=16) <= 0xff: 9303101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 9313101Sstever@eecs.umich.edu 9323101Sstever@eecs.umich.edu self.value = value 9333101Sstever@eecs.umich.edu 93410267SGeoffrey.Blake@arm.com def __call__(self, value): 93510267SGeoffrey.Blake@arm.com self.__init__(value) 93610267SGeoffrey.Blake@arm.com return value 93710267SGeoffrey.Blake@arm.com 9383101Sstever@eecs.umich.edu def unproxy(self, base): 9393101Sstever@eecs.umich.edu if self.value == NextEthernetAddr: 9404380Sbinkertn@umich.edu return EthernetAddr(self.value()) 9413101Sstever@eecs.umich.edu return self 9423101Sstever@eecs.umich.edu 9434762Snate@binkert.org def getValue(self): 9447677Snate@binkert.org from m5.internal.params import EthAddr 9454762Snate@binkert.org return EthAddr(self.value) 9464762Snate@binkert.org 94711228SAndrew.Bardsley@arm.com def __str__(self): 94811228SAndrew.Bardsley@arm.com return self.value 94911228SAndrew.Bardsley@arm.com 9504380Sbinkertn@umich.edu def ini_str(self): 9514380Sbinkertn@umich.edu return self.value 9523101Sstever@eecs.umich.edu 95310458Sandreas.hansson@arm.com @classmethod 95410458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 95510458Sandreas.hansson@arm.com code('%s = Net::EthAddr(%s);' % (dest, src)) 95610458Sandreas.hansson@arm.com code('%s true;' % ret) 95710458Sandreas.hansson@arm.com 9587777Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of 9597777Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP. 9607777Sgblack@eecs.umich.educlass IpAddress(ParamValue): 9617777Sgblack@eecs.umich.edu cxx_type = 'Net::IpAddress' 96210267SGeoffrey.Blake@arm.com ex_str = "127.0.0.1" 96310267SGeoffrey.Blake@arm.com cmd_line_settable = True 9647777Sgblack@eecs.umich.edu 9657777Sgblack@eecs.umich.edu @classmethod 9667777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 9677777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 9687777Sgblack@eecs.umich.edu 9697777Sgblack@eecs.umich.edu @classmethod 9707777Sgblack@eecs.umich.edu def swig_predecls(cls, code): 9717777Sgblack@eecs.umich.edu code('%include "python/swig/inet.i"') 9727777Sgblack@eecs.umich.edu 9737777Sgblack@eecs.umich.edu def __init__(self, value): 9747777Sgblack@eecs.umich.edu if isinstance(value, IpAddress): 9757777Sgblack@eecs.umich.edu self.ip = value.ip 9767777Sgblack@eecs.umich.edu else: 9777777Sgblack@eecs.umich.edu try: 9787777Sgblack@eecs.umich.edu self.ip = convert.toIpAddress(value) 9797777Sgblack@eecs.umich.edu except TypeError: 9807777Sgblack@eecs.umich.edu self.ip = long(value) 9817777Sgblack@eecs.umich.edu self.verifyIp() 9827777Sgblack@eecs.umich.edu 98310267SGeoffrey.Blake@arm.com def __call__(self, value): 98410267SGeoffrey.Blake@arm.com self.__init__(value) 98510267SGeoffrey.Blake@arm.com return value 98610267SGeoffrey.Blake@arm.com 9878579Ssteve.reinhardt@amd.com def __str__(self): 9888579Ssteve.reinhardt@amd.com tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)] 9898579Ssteve.reinhardt@amd.com return '%d.%d.%d.%d' % tuple(tup) 9908579Ssteve.reinhardt@amd.com 9918579Ssteve.reinhardt@amd.com def __eq__(self, other): 9928579Ssteve.reinhardt@amd.com if isinstance(other, IpAddress): 9938579Ssteve.reinhardt@amd.com return self.ip == other.ip 9948579Ssteve.reinhardt@amd.com elif isinstance(other, str): 9958579Ssteve.reinhardt@amd.com try: 9968579Ssteve.reinhardt@amd.com return self.ip == convert.toIpAddress(other) 9978579Ssteve.reinhardt@amd.com except: 9988579Ssteve.reinhardt@amd.com return False 9998579Ssteve.reinhardt@amd.com else: 10008579Ssteve.reinhardt@amd.com return self.ip == other 10018579Ssteve.reinhardt@amd.com 10028579Ssteve.reinhardt@amd.com def __ne__(self, other): 10038579Ssteve.reinhardt@amd.com return not (self == other) 10048579Ssteve.reinhardt@amd.com 10057777Sgblack@eecs.umich.edu def verifyIp(self): 10067777Sgblack@eecs.umich.edu if self.ip < 0 or self.ip >= (1 << 32): 10077798Sgblack@eecs.umich.edu raise TypeError, "invalid ip address %#08x" % self.ip 10087777Sgblack@eecs.umich.edu 10097777Sgblack@eecs.umich.edu def getValue(self): 10107777Sgblack@eecs.umich.edu from m5.internal.params import IpAddress 10117777Sgblack@eecs.umich.edu return IpAddress(self.ip) 10127777Sgblack@eecs.umich.edu 10137777Sgblack@eecs.umich.edu# When initializing an IpNetmask, pass in an existing IpNetmask, a string of 10147777Sgblack@eecs.umich.edu# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as 10157777Sgblack@eecs.umich.edu# positional or keyword arguments. 10167777Sgblack@eecs.umich.educlass IpNetmask(IpAddress): 10177777Sgblack@eecs.umich.edu cxx_type = 'Net::IpNetmask' 101810267SGeoffrey.Blake@arm.com ex_str = "127.0.0.0/24" 101910267SGeoffrey.Blake@arm.com cmd_line_settable = True 10207777Sgblack@eecs.umich.edu 10217777Sgblack@eecs.umich.edu @classmethod 10227777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 10237777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 10247777Sgblack@eecs.umich.edu 10257777Sgblack@eecs.umich.edu @classmethod 10267777Sgblack@eecs.umich.edu def swig_predecls(cls, code): 10277777Sgblack@eecs.umich.edu code('%include "python/swig/inet.i"') 10287777Sgblack@eecs.umich.edu 10297777Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 10307777Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 10317777Sgblack@eecs.umich.edu if key in kwargs: 10327777Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 10337777Sgblack@eecs.umich.edu elif elseVal: 10347777Sgblack@eecs.umich.edu setattr(self, key, elseVal) 10357777Sgblack@eecs.umich.edu else: 10367777Sgblack@eecs.umich.edu raise TypeError, "No value set for %s" % key 10377777Sgblack@eecs.umich.edu 10387777Sgblack@eecs.umich.edu if len(args) == 0: 10397777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip') 10407777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask') 10417777Sgblack@eecs.umich.edu 10427777Sgblack@eecs.umich.edu elif len(args) == 1: 10437777Sgblack@eecs.umich.edu if kwargs: 10447777Sgblack@eecs.umich.edu if not 'ip' in kwargs and not 'netmask' in kwargs: 10457777Sgblack@eecs.umich.edu raise TypeError, "Invalid arguments" 10467777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 10477777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask', args[0]) 10487777Sgblack@eecs.umich.edu elif isinstance(args[0], IpNetmask): 10497777Sgblack@eecs.umich.edu self.ip = args[0].ip 10507777Sgblack@eecs.umich.edu self.netmask = args[0].netmask 10517777Sgblack@eecs.umich.edu else: 10527777Sgblack@eecs.umich.edu (self.ip, self.netmask) = convert.toIpNetmask(args[0]) 10537777Sgblack@eecs.umich.edu 10547777Sgblack@eecs.umich.edu elif len(args) == 2: 10557777Sgblack@eecs.umich.edu self.ip = args[0] 10567777Sgblack@eecs.umich.edu self.netmask = args[1] 10577777Sgblack@eecs.umich.edu else: 10587777Sgblack@eecs.umich.edu raise TypeError, "Too many arguments specified" 10597777Sgblack@eecs.umich.edu 10607777Sgblack@eecs.umich.edu if kwargs: 10617777Sgblack@eecs.umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 10627777Sgblack@eecs.umich.edu 10637777Sgblack@eecs.umich.edu self.verify() 10647777Sgblack@eecs.umich.edu 106510267SGeoffrey.Blake@arm.com def __call__(self, value): 106610267SGeoffrey.Blake@arm.com self.__init__(value) 106710267SGeoffrey.Blake@arm.com return value 106810267SGeoffrey.Blake@arm.com 10698579Ssteve.reinhardt@amd.com def __str__(self): 10708579Ssteve.reinhardt@amd.com return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask) 10718579Ssteve.reinhardt@amd.com 10728579Ssteve.reinhardt@amd.com def __eq__(self, other): 10738579Ssteve.reinhardt@amd.com if isinstance(other, IpNetmask): 10748579Ssteve.reinhardt@amd.com return self.ip == other.ip and self.netmask == other.netmask 10758579Ssteve.reinhardt@amd.com elif isinstance(other, str): 10768579Ssteve.reinhardt@amd.com try: 10778579Ssteve.reinhardt@amd.com return (self.ip, self.netmask) == convert.toIpNetmask(other) 10788579Ssteve.reinhardt@amd.com except: 10798579Ssteve.reinhardt@amd.com return False 10808579Ssteve.reinhardt@amd.com else: 10818579Ssteve.reinhardt@amd.com return False 10828579Ssteve.reinhardt@amd.com 10837777Sgblack@eecs.umich.edu def verify(self): 10847777Sgblack@eecs.umich.edu self.verifyIp() 10857777Sgblack@eecs.umich.edu if self.netmask < 0 or self.netmask > 32: 10867777Sgblack@eecs.umich.edu raise TypeError, "invalid netmask %d" % netmask 10877777Sgblack@eecs.umich.edu 10887777Sgblack@eecs.umich.edu def getValue(self): 10897777Sgblack@eecs.umich.edu from m5.internal.params import IpNetmask 10907777Sgblack@eecs.umich.edu return IpNetmask(self.ip, self.netmask) 10917777Sgblack@eecs.umich.edu 10927777Sgblack@eecs.umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of 10937777Sgblack@eecs.umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments. 10947777Sgblack@eecs.umich.educlass IpWithPort(IpAddress): 10957777Sgblack@eecs.umich.edu cxx_type = 'Net::IpWithPort' 109610267SGeoffrey.Blake@arm.com ex_str = "127.0.0.1:80" 109710267SGeoffrey.Blake@arm.com cmd_line_settable = True 10987777Sgblack@eecs.umich.edu 10997777Sgblack@eecs.umich.edu @classmethod 11007777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 11017777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 11027777Sgblack@eecs.umich.edu 11037777Sgblack@eecs.umich.edu @classmethod 11047777Sgblack@eecs.umich.edu def swig_predecls(cls, code): 11057777Sgblack@eecs.umich.edu code('%include "python/swig/inet.i"') 11067777Sgblack@eecs.umich.edu 11077777Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 11087777Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 11097777Sgblack@eecs.umich.edu if key in kwargs: 11107777Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 11117777Sgblack@eecs.umich.edu elif elseVal: 11127777Sgblack@eecs.umich.edu setattr(self, key, elseVal) 11137777Sgblack@eecs.umich.edu else: 11147777Sgblack@eecs.umich.edu raise TypeError, "No value set for %s" % key 11157777Sgblack@eecs.umich.edu 11167777Sgblack@eecs.umich.edu if len(args) == 0: 11177777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip') 11187777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'port') 11197777Sgblack@eecs.umich.edu 11207777Sgblack@eecs.umich.edu elif len(args) == 1: 11217777Sgblack@eecs.umich.edu if kwargs: 11227777Sgblack@eecs.umich.edu if not 'ip' in kwargs and not 'port' in kwargs: 11237777Sgblack@eecs.umich.edu raise TypeError, "Invalid arguments" 11247777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 11257777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'port', args[0]) 11267777Sgblack@eecs.umich.edu elif isinstance(args[0], IpWithPort): 11277777Sgblack@eecs.umich.edu self.ip = args[0].ip 11287777Sgblack@eecs.umich.edu self.port = args[0].port 11297777Sgblack@eecs.umich.edu else: 11307777Sgblack@eecs.umich.edu (self.ip, self.port) = convert.toIpWithPort(args[0]) 11317777Sgblack@eecs.umich.edu 11327777Sgblack@eecs.umich.edu elif len(args) == 2: 11337777Sgblack@eecs.umich.edu self.ip = args[0] 11347777Sgblack@eecs.umich.edu self.port = args[1] 11357777Sgblack@eecs.umich.edu else: 11367777Sgblack@eecs.umich.edu raise TypeError, "Too many arguments specified" 11377777Sgblack@eecs.umich.edu 11387777Sgblack@eecs.umich.edu if kwargs: 11397777Sgblack@eecs.umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 11407777Sgblack@eecs.umich.edu 11417777Sgblack@eecs.umich.edu self.verify() 11427777Sgblack@eecs.umich.edu 114310267SGeoffrey.Blake@arm.com def __call__(self, value): 114410267SGeoffrey.Blake@arm.com self.__init__(value) 114510267SGeoffrey.Blake@arm.com return value 114610267SGeoffrey.Blake@arm.com 11478579Ssteve.reinhardt@amd.com def __str__(self): 11488579Ssteve.reinhardt@amd.com return "%s:%d" % (super(IpWithPort, self).__str__(), self.port) 11498579Ssteve.reinhardt@amd.com 11508579Ssteve.reinhardt@amd.com def __eq__(self, other): 11518579Ssteve.reinhardt@amd.com if isinstance(other, IpWithPort): 11528579Ssteve.reinhardt@amd.com return self.ip == other.ip and self.port == other.port 11538579Ssteve.reinhardt@amd.com elif isinstance(other, str): 11548579Ssteve.reinhardt@amd.com try: 11558579Ssteve.reinhardt@amd.com return (self.ip, self.port) == convert.toIpWithPort(other) 11568579Ssteve.reinhardt@amd.com except: 11578579Ssteve.reinhardt@amd.com return False 11588579Ssteve.reinhardt@amd.com else: 11598579Ssteve.reinhardt@amd.com return False 11608579Ssteve.reinhardt@amd.com 11617777Sgblack@eecs.umich.edu def verify(self): 11627777Sgblack@eecs.umich.edu self.verifyIp() 11637777Sgblack@eecs.umich.edu if self.port < 0 or self.port > 0xffff: 11647777Sgblack@eecs.umich.edu raise TypeError, "invalid port %d" % self.port 11657777Sgblack@eecs.umich.edu 11667777Sgblack@eecs.umich.edu def getValue(self): 11677777Sgblack@eecs.umich.edu from m5.internal.params import IpWithPort 11687777Sgblack@eecs.umich.edu return IpWithPort(self.ip, self.port) 11697777Sgblack@eecs.umich.edu 11703932Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 117110380SAndrew.Bardsley@arm.com "%a %b %d %H:%M:%S %Y", 11723932Sbinkertn@umich.edu "%Y/%m/%d %H:%M:%S", 11733932Sbinkertn@umich.edu "%Y/%m/%d %H:%M", 11743932Sbinkertn@umich.edu "%Y/%m/%d", 11753932Sbinkertn@umich.edu "%m/%d/%Y %H:%M:%S", 11763932Sbinkertn@umich.edu "%m/%d/%Y %H:%M", 11773932Sbinkertn@umich.edu "%m/%d/%Y", 11783932Sbinkertn@umich.edu "%m/%d/%y %H:%M:%S", 11793932Sbinkertn@umich.edu "%m/%d/%y %H:%M", 11803932Sbinkertn@umich.edu "%m/%d/%y"] 11813932Sbinkertn@umich.edu 11823932Sbinkertn@umich.edu 11833885Sbinkertn@umich.edudef parse_time(value): 11843932Sbinkertn@umich.edu from time import gmtime, strptime, struct_time, time 11853932Sbinkertn@umich.edu from datetime import datetime, date 11863885Sbinkertn@umich.edu 11873932Sbinkertn@umich.edu if isinstance(value, struct_time): 11883932Sbinkertn@umich.edu return value 11893932Sbinkertn@umich.edu 11903932Sbinkertn@umich.edu if isinstance(value, (int, long)): 11913932Sbinkertn@umich.edu return gmtime(value) 11923932Sbinkertn@umich.edu 11933932Sbinkertn@umich.edu if isinstance(value, (datetime, date)): 11943932Sbinkertn@umich.edu return value.timetuple() 11953932Sbinkertn@umich.edu 11963932Sbinkertn@umich.edu if isinstance(value, str): 11973932Sbinkertn@umich.edu if value in ('Now', 'Today'): 11983932Sbinkertn@umich.edu return time.gmtime(time.time()) 11993932Sbinkertn@umich.edu 12003932Sbinkertn@umich.edu for format in time_formats: 12013932Sbinkertn@umich.edu try: 12023932Sbinkertn@umich.edu return strptime(value, format) 12033932Sbinkertn@umich.edu except ValueError: 12043932Sbinkertn@umich.edu pass 12053885Sbinkertn@umich.edu 12063885Sbinkertn@umich.edu raise ValueError, "Could not parse '%s' as a time" % value 12073885Sbinkertn@umich.edu 12083885Sbinkertn@umich.educlass Time(ParamValue): 12094762Snate@binkert.org cxx_type = 'tm' 12107673Snate@binkert.org 12117673Snate@binkert.org @classmethod 12127673Snate@binkert.org def cxx_predecls(cls, code): 12137673Snate@binkert.org code('#include <time.h>') 12147673Snate@binkert.org 12157673Snate@binkert.org @classmethod 12167673Snate@binkert.org def swig_predecls(cls, code): 12177673Snate@binkert.org code('%include "python/swig/time.i"') 12187673Snate@binkert.org 12193885Sbinkertn@umich.edu def __init__(self, value): 12203932Sbinkertn@umich.edu self.value = parse_time(value) 12213885Sbinkertn@umich.edu 122210267SGeoffrey.Blake@arm.com def __call__(self, value): 122310267SGeoffrey.Blake@arm.com self.__init__(value) 122410267SGeoffrey.Blake@arm.com return value 122510267SGeoffrey.Blake@arm.com 12264762Snate@binkert.org def getValue(self): 12277677Snate@binkert.org from m5.internal.params import tm 12284762Snate@binkert.org 12294762Snate@binkert.org c_time = tm() 12304762Snate@binkert.org py_time = self.value 12314762Snate@binkert.org 12324762Snate@binkert.org # UNIX is years since 1900 12334762Snate@binkert.org c_time.tm_year = py_time.tm_year - 1900; 12344762Snate@binkert.org 12354762Snate@binkert.org # Python starts at 1, UNIX starts at 0 12364762Snate@binkert.org c_time.tm_mon = py_time.tm_mon - 1; 12374762Snate@binkert.org c_time.tm_mday = py_time.tm_mday; 12384762Snate@binkert.org c_time.tm_hour = py_time.tm_hour; 12394762Snate@binkert.org c_time.tm_min = py_time.tm_min; 12404762Snate@binkert.org c_time.tm_sec = py_time.tm_sec; 12414762Snate@binkert.org 12424762Snate@binkert.org # Python has 0 as Monday, UNIX is 0 as sunday 12434762Snate@binkert.org c_time.tm_wday = py_time.tm_wday + 1 12444762Snate@binkert.org if c_time.tm_wday > 6: 12454762Snate@binkert.org c_time.tm_wday -= 7; 12464762Snate@binkert.org 12474762Snate@binkert.org # Python starts at 1, Unix starts at 0 12484762Snate@binkert.org c_time.tm_yday = py_time.tm_yday - 1; 12494762Snate@binkert.org 12504762Snate@binkert.org return c_time 12514762Snate@binkert.org 12523885Sbinkertn@umich.edu def __str__(self): 12534762Snate@binkert.org return time.asctime(self.value) 12543885Sbinkertn@umich.edu 12553885Sbinkertn@umich.edu def ini_str(self): 12563932Sbinkertn@umich.edu return str(self) 12573885Sbinkertn@umich.edu 12588664SAli.Saidi@ARM.com def get_config_as_dict(self): 125910380SAndrew.Bardsley@arm.com assert false 12608664SAli.Saidi@ARM.com return str(self) 12618664SAli.Saidi@ARM.com 126210458Sandreas.hansson@arm.com @classmethod 126310458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 126410458Sandreas.hansson@arm.com code('#include <time.h>') 126510458Sandreas.hansson@arm.com 126610458Sandreas.hansson@arm.com @classmethod 126710458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 126810458Sandreas.hansson@arm.com code('char *_parse_ret = strptime((${src}).c_str(),') 126910458Sandreas.hansson@arm.com code(' "%a %b %d %H:%M:%S %Y", &(${dest}));') 127010458Sandreas.hansson@arm.com code('${ret} _parse_ret && *_parse_ret == \'\\0\';'); 127110458Sandreas.hansson@arm.com 12723101Sstever@eecs.umich.edu# Enumerated types are a little more complex. The user specifies the 12733101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of 12743101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so). (In the 12753101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index 12763101Sstever@eecs.umich.edu# or the corresponding dictionary value. For now, since we only check 12773101Sstever@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file, 12783101Sstever@eecs.umich.edu# there's not much point in using the dictionary.) 12793101Sstever@eecs.umich.edu 12803101Sstever@eecs.umich.edu# What Enum() must do is generate a new type encapsulating the 12813101Sstever@eecs.umich.edu# provided list/dictionary so that specific values of the parameter 12823101Sstever@eecs.umich.edu# can be instances of that type. We define two hidden internal 12833101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then 12843101Sstever@eecs.umich.edu# derive the new type from the appropriate base class on the fly. 12853101Sstever@eecs.umich.edu 12864762Snate@binkert.orgallEnums = {} 12873101Sstever@eecs.umich.edu# Metaclass for Enum types 12885033Smilesck@eecs.umich.educlass MetaEnum(MetaParamValue): 12894762Snate@binkert.org def __new__(mcls, name, bases, dict): 12904762Snate@binkert.org assert name not in allEnums 12914762Snate@binkert.org 12924762Snate@binkert.org cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 12934762Snate@binkert.org allEnums[name] = cls 12944762Snate@binkert.org return cls 12954762Snate@binkert.org 12963101Sstever@eecs.umich.edu def __init__(cls, name, bases, init_dict): 12973101Sstever@eecs.umich.edu if init_dict.has_key('map'): 12983101Sstever@eecs.umich.edu if not isinstance(cls.map, dict): 12993101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'map' " \ 13003101Sstever@eecs.umich.edu "must be of type dict" 13013101Sstever@eecs.umich.edu # build list of value strings from map 13023101Sstever@eecs.umich.edu cls.vals = cls.map.keys() 13033101Sstever@eecs.umich.edu cls.vals.sort() 13043101Sstever@eecs.umich.edu elif init_dict.has_key('vals'): 13053101Sstever@eecs.umich.edu if not isinstance(cls.vals, list): 13063101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'vals' " \ 13073101Sstever@eecs.umich.edu "must be of type list" 13083101Sstever@eecs.umich.edu # build string->value map from vals sequence 13093101Sstever@eecs.umich.edu cls.map = {} 13103101Sstever@eecs.umich.edu for idx,val in enumerate(cls.vals): 13113101Sstever@eecs.umich.edu cls.map[val] = idx 13123101Sstever@eecs.umich.edu else: 13133101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class must define "\ 13143101Sstever@eecs.umich.edu "attribute 'map' or 'vals'" 13153101Sstever@eecs.umich.edu 13164762Snate@binkert.org cls.cxx_type = 'Enums::%s' % name 13173101Sstever@eecs.umich.edu 13183101Sstever@eecs.umich.edu super(MetaEnum, cls).__init__(name, bases, init_dict) 13193101Sstever@eecs.umich.edu 13203101Sstever@eecs.umich.edu # Generate C++ class declaration for this enum type. 13213101Sstever@eecs.umich.edu # Note that we wrap the enum in a class/struct to act as a namespace, 13223101Sstever@eecs.umich.edu # so that the enum strings can be brief w/o worrying about collisions. 13237673Snate@binkert.org def cxx_decl(cls, code): 132410201SAndrew.Bardsley@arm.com wrapper_name = cls.wrapper_name 132510201SAndrew.Bardsley@arm.com wrapper = 'struct' if cls.wrapper_is_struct else 'namespace' 132610201SAndrew.Bardsley@arm.com name = cls.__name__ if cls.enum_name is None else cls.enum_name 132710201SAndrew.Bardsley@arm.com idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name) 132810201SAndrew.Bardsley@arm.com 13297673Snate@binkert.org code('''\ 133010201SAndrew.Bardsley@arm.com#ifndef $idem_macro 133110201SAndrew.Bardsley@arm.com#define $idem_macro 13327673Snate@binkert.org 133310201SAndrew.Bardsley@arm.com$wrapper $wrapper_name { 13347673Snate@binkert.org enum $name { 13357673Snate@binkert.org''') 13367673Snate@binkert.org code.indent(2) 13374762Snate@binkert.org for val in cls.vals: 13387673Snate@binkert.org code('$val = ${{cls.map[val]}},') 13398902Sandreas.hansson@arm.com code('Num_$name = ${{len(cls.vals)}}') 13407673Snate@binkert.org code.dedent(2) 134110201SAndrew.Bardsley@arm.com code(' };') 13424762Snate@binkert.org 134310201SAndrew.Bardsley@arm.com if cls.wrapper_is_struct: 134410201SAndrew.Bardsley@arm.com code(' static const char *${name}Strings[Num_${name}];') 134510201SAndrew.Bardsley@arm.com code('};') 134610201SAndrew.Bardsley@arm.com else: 134710201SAndrew.Bardsley@arm.com code('extern const char *${name}Strings[Num_${name}];') 134810201SAndrew.Bardsley@arm.com code('}') 134910201SAndrew.Bardsley@arm.com 135010201SAndrew.Bardsley@arm.com code() 135110201SAndrew.Bardsley@arm.com code('#endif // $idem_macro') 13527673Snate@binkert.org 13537673Snate@binkert.org def cxx_def(cls, code): 135410201SAndrew.Bardsley@arm.com wrapper_name = cls.wrapper_name 135510201SAndrew.Bardsley@arm.com file_name = cls.__name__ 135610201SAndrew.Bardsley@arm.com name = cls.__name__ if cls.enum_name is None else cls.enum_name 135710201SAndrew.Bardsley@arm.com 135810201SAndrew.Bardsley@arm.com code('#include "enums/$file_name.hh"') 135910201SAndrew.Bardsley@arm.com if cls.wrapper_is_struct: 136010201SAndrew.Bardsley@arm.com code('const char *${wrapper_name}::${name}Strings' 136110201SAndrew.Bardsley@arm.com '[Num_${name}] =') 136210201SAndrew.Bardsley@arm.com else: 136310201SAndrew.Bardsley@arm.com code('namespace Enums {') 136410201SAndrew.Bardsley@arm.com code.indent(1) 136510201SAndrew.Bardsley@arm.com code(' const char *${name}Strings[Num_${name}] =') 136610201SAndrew.Bardsley@arm.com 136710201SAndrew.Bardsley@arm.com code('{') 136810201SAndrew.Bardsley@arm.com code.indent(1) 13694762Snate@binkert.org for val in cls.vals: 13707673Snate@binkert.org code('"$val",') 137110201SAndrew.Bardsley@arm.com code.dedent(1) 137210201SAndrew.Bardsley@arm.com code('};') 137310201SAndrew.Bardsley@arm.com 137410201SAndrew.Bardsley@arm.com if not cls.wrapper_is_struct: 137510201SAndrew.Bardsley@arm.com code('} // namespace $wrapper_name') 137610201SAndrew.Bardsley@arm.com code.dedent(1) 13773101Sstever@eecs.umich.edu 13788596Ssteve.reinhardt@amd.com def swig_decl(cls, code): 13798596Ssteve.reinhardt@amd.com name = cls.__name__ 13808596Ssteve.reinhardt@amd.com code('''\ 138111802Sandreas.sandberg@arm.com%module(package="_m5") enum_$name 13828596Ssteve.reinhardt@amd.com 13838596Ssteve.reinhardt@amd.com%{ 13848596Ssteve.reinhardt@amd.com#include "enums/$name.hh" 13858596Ssteve.reinhardt@amd.com%} 13868596Ssteve.reinhardt@amd.com 13878596Ssteve.reinhardt@amd.com%include "enums/$name.hh" 13888596Ssteve.reinhardt@amd.com''') 13898596Ssteve.reinhardt@amd.com 13908596Ssteve.reinhardt@amd.com 13913101Sstever@eecs.umich.edu# Base class for enum types. 13923101Sstever@eecs.umich.educlass Enum(ParamValue): 13933101Sstever@eecs.umich.edu __metaclass__ = MetaEnum 13943101Sstever@eecs.umich.edu vals = [] 139510267SGeoffrey.Blake@arm.com cmd_line_settable = True 13963101Sstever@eecs.umich.edu 139710201SAndrew.Bardsley@arm.com # The name of the wrapping namespace or struct 139810201SAndrew.Bardsley@arm.com wrapper_name = 'Enums' 139910201SAndrew.Bardsley@arm.com 140010201SAndrew.Bardsley@arm.com # If true, the enum is wrapped in a struct rather than a namespace 140110201SAndrew.Bardsley@arm.com wrapper_is_struct = False 140210201SAndrew.Bardsley@arm.com 140310201SAndrew.Bardsley@arm.com # If not None, use this as the enum name rather than this class name 140410201SAndrew.Bardsley@arm.com enum_name = None 140510201SAndrew.Bardsley@arm.com 14063101Sstever@eecs.umich.edu def __init__(self, value): 14073101Sstever@eecs.umich.edu if value not in self.map: 14083101Sstever@eecs.umich.edu raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 14093101Sstever@eecs.umich.edu % (value, self.vals) 14103101Sstever@eecs.umich.edu self.value = value 14113101Sstever@eecs.umich.edu 141210267SGeoffrey.Blake@arm.com def __call__(self, value): 141310267SGeoffrey.Blake@arm.com self.__init__(value) 141410267SGeoffrey.Blake@arm.com return value 141510267SGeoffrey.Blake@arm.com 14167675Snate@binkert.org @classmethod 14177675Snate@binkert.org def cxx_predecls(cls, code): 14187675Snate@binkert.org code('#include "enums/$0.hh"', cls.__name__) 14197675Snate@binkert.org 14207675Snate@binkert.org @classmethod 14217675Snate@binkert.org def swig_predecls(cls, code): 142211802Sandreas.sandberg@arm.com code('%import "python/_m5/enum_$0.i"', cls.__name__) 14237675Snate@binkert.org 142410458Sandreas.hansson@arm.com @classmethod 142510458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 142610458Sandreas.hansson@arm.com code('if (false) {') 142710458Sandreas.hansson@arm.com for elem_name in cls.map.iterkeys(): 142810458Sandreas.hansson@arm.com code('} else if (%s == "%s") {' % (src, elem_name)) 142910458Sandreas.hansson@arm.com code.indent() 143010458Sandreas.hansson@arm.com code('%s = Enums::%s;' % (dest, elem_name)) 143110458Sandreas.hansson@arm.com code('%s true;' % ret) 143210458Sandreas.hansson@arm.com code.dedent() 143310458Sandreas.hansson@arm.com code('} else {') 143410458Sandreas.hansson@arm.com code(' %s false;' % ret) 143510458Sandreas.hansson@arm.com code('}') 143610458Sandreas.hansson@arm.com 14374762Snate@binkert.org def getValue(self): 14384762Snate@binkert.org return int(self.map[self.value]) 14394762Snate@binkert.org 14403101Sstever@eecs.umich.edu def __str__(self): 14413101Sstever@eecs.umich.edu return self.value 14423101Sstever@eecs.umich.edu 14433101Sstever@eecs.umich.edu# how big does a rounding error need to be before we warn about it? 14443101Sstever@eecs.umich.edufrequency_tolerance = 0.001 # 0.1% 14453101Sstever@eecs.umich.edu 14464167Sbinkertn@umich.educlass TickParamValue(NumericParamValue): 14473101Sstever@eecs.umich.edu cxx_type = 'Tick' 144810267SGeoffrey.Blake@arm.com ex_str = "1MHz" 144910267SGeoffrey.Blake@arm.com cmd_line_settable = True 14507673Snate@binkert.org 14517673Snate@binkert.org @classmethod 14527673Snate@binkert.org def cxx_predecls(cls, code): 14537673Snate@binkert.org code('#include "base/types.hh"') 14547673Snate@binkert.org 14557673Snate@binkert.org @classmethod 14567673Snate@binkert.org def swig_predecls(cls, code): 14577673Snate@binkert.org code('%import "stdint.i"') 14587673Snate@binkert.org code('%import "base/types.hh"') 14594167Sbinkertn@umich.edu 146010267SGeoffrey.Blake@arm.com def __call__(self, value): 146110267SGeoffrey.Blake@arm.com self.__init__(value) 146210267SGeoffrey.Blake@arm.com return value 146310267SGeoffrey.Blake@arm.com 14644762Snate@binkert.org def getValue(self): 14654762Snate@binkert.org return long(self.value) 14664762Snate@binkert.org 146710458Sandreas.hansson@arm.com @classmethod 146810458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 146910458Sandreas.hansson@arm.com code('#include <sstream>') 147010458Sandreas.hansson@arm.com 147110458Sandreas.hansson@arm.com # Ticks are expressed in seconds in JSON files and in plain 147210458Sandreas.hansson@arm.com # Ticks in .ini files. Switch based on a config flag 147310458Sandreas.hansson@arm.com @classmethod 147410458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 147510458Sandreas.hansson@arm.com code('${ret} to_number(${src}, ${dest});') 147610458Sandreas.hansson@arm.com 14774167Sbinkertn@umich.educlass Latency(TickParamValue): 147810267SGeoffrey.Blake@arm.com ex_str = "100ns" 147910267SGeoffrey.Blake@arm.com 14803101Sstever@eecs.umich.edu def __init__(self, value): 14814167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 14824167Sbinkertn@umich.edu self.ticks = value.ticks 14834167Sbinkertn@umich.edu self.value = value.value 14844167Sbinkertn@umich.edu elif isinstance(value, Frequency): 14854167Sbinkertn@umich.edu self.ticks = value.ticks 14864167Sbinkertn@umich.edu self.value = 1.0 / value.value 14874167Sbinkertn@umich.edu elif value.endswith('t'): 14884167Sbinkertn@umich.edu self.ticks = True 14894167Sbinkertn@umich.edu self.value = int(value[:-1]) 14904167Sbinkertn@umich.edu else: 14914167Sbinkertn@umich.edu self.ticks = False 14924167Sbinkertn@umich.edu self.value = convert.toLatency(value) 14933101Sstever@eecs.umich.edu 149410267SGeoffrey.Blake@arm.com def __call__(self, value): 149510267SGeoffrey.Blake@arm.com self.__init__(value) 149610267SGeoffrey.Blake@arm.com return value 149710267SGeoffrey.Blake@arm.com 14983101Sstever@eecs.umich.edu def __getattr__(self, attr): 14993101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 15003101Sstever@eecs.umich.edu return self 15013101Sstever@eecs.umich.edu if attr == 'frequency': 15023101Sstever@eecs.umich.edu return Frequency(self) 15033101Sstever@eecs.umich.edu raise AttributeError, "Latency object has no attribute '%s'" % attr 15043101Sstever@eecs.umich.edu 15054762Snate@binkert.org def getValue(self): 15064762Snate@binkert.org if self.ticks or self.value == 0: 15074762Snate@binkert.org value = self.value 15084762Snate@binkert.org else: 15094762Snate@binkert.org value = ticks.fromSeconds(self.value) 15104762Snate@binkert.org return long(value) 15114762Snate@binkert.org 151210380SAndrew.Bardsley@arm.com def config_value(self): 151310380SAndrew.Bardsley@arm.com return self.getValue() 151410380SAndrew.Bardsley@arm.com 15153101Sstever@eecs.umich.edu # convert latency to ticks 15163101Sstever@eecs.umich.edu def ini_str(self): 15174762Snate@binkert.org return '%d' % self.getValue() 15183101Sstever@eecs.umich.edu 15194167Sbinkertn@umich.educlass Frequency(TickParamValue): 152010267SGeoffrey.Blake@arm.com ex_str = "1GHz" 152110267SGeoffrey.Blake@arm.com 15223101Sstever@eecs.umich.edu def __init__(self, value): 15234167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 15244167Sbinkertn@umich.edu if value.value == 0: 15254167Sbinkertn@umich.edu self.value = 0 15264167Sbinkertn@umich.edu else: 15274167Sbinkertn@umich.edu self.value = 1.0 / value.value 15284167Sbinkertn@umich.edu self.ticks = value.ticks 15294167Sbinkertn@umich.edu elif isinstance(value, Frequency): 15304167Sbinkertn@umich.edu self.value = value.value 15314167Sbinkertn@umich.edu self.ticks = value.ticks 15324167Sbinkertn@umich.edu else: 15334167Sbinkertn@umich.edu self.ticks = False 15344167Sbinkertn@umich.edu self.value = convert.toFrequency(value) 15353101Sstever@eecs.umich.edu 153610267SGeoffrey.Blake@arm.com def __call__(self, value): 153710267SGeoffrey.Blake@arm.com self.__init__(value) 153810267SGeoffrey.Blake@arm.com return value 153910267SGeoffrey.Blake@arm.com 15403101Sstever@eecs.umich.edu def __getattr__(self, attr): 15413101Sstever@eecs.umich.edu if attr == 'frequency': 15423101Sstever@eecs.umich.edu return self 15433101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 15443101Sstever@eecs.umich.edu return Latency(self) 15453101Sstever@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 15463101Sstever@eecs.umich.edu 15474167Sbinkertn@umich.edu # convert latency to ticks 15484762Snate@binkert.org def getValue(self): 15494762Snate@binkert.org if self.ticks or self.value == 0: 15504762Snate@binkert.org value = self.value 15514762Snate@binkert.org else: 15524762Snate@binkert.org value = ticks.fromSeconds(1.0 / self.value) 15534762Snate@binkert.org return long(value) 15544762Snate@binkert.org 155510380SAndrew.Bardsley@arm.com def config_value(self): 155610380SAndrew.Bardsley@arm.com return self.getValue() 155710380SAndrew.Bardsley@arm.com 15583101Sstever@eecs.umich.edu def ini_str(self): 15594762Snate@binkert.org return '%d' % self.getValue() 15603101Sstever@eecs.umich.edu 156110019Sandreas.hansson@arm.com# A generic Frequency and/or Latency value. Value is stored as a 156210019Sandreas.hansson@arm.com# latency, just like Latency and Frequency. 156310019Sandreas.hansson@arm.comclass Clock(TickParamValue): 15643101Sstever@eecs.umich.edu def __init__(self, value): 15654167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 15664167Sbinkertn@umich.edu self.ticks = value.ticks 15674167Sbinkertn@umich.edu self.value = value.value 15684167Sbinkertn@umich.edu elif isinstance(value, Frequency): 15694167Sbinkertn@umich.edu self.ticks = value.ticks 15704167Sbinkertn@umich.edu self.value = 1.0 / value.value 15714167Sbinkertn@umich.edu elif value.endswith('t'): 15724167Sbinkertn@umich.edu self.ticks = True 15734167Sbinkertn@umich.edu self.value = int(value[:-1]) 15744167Sbinkertn@umich.edu else: 15754167Sbinkertn@umich.edu self.ticks = False 15764167Sbinkertn@umich.edu self.value = convert.anyToLatency(value) 15773101Sstever@eecs.umich.edu 157810267SGeoffrey.Blake@arm.com def __call__(self, value): 157910267SGeoffrey.Blake@arm.com self.__init__(value) 158010267SGeoffrey.Blake@arm.com return value 158110267SGeoffrey.Blake@arm.com 158210267SGeoffrey.Blake@arm.com def __str__(self): 158310267SGeoffrey.Blake@arm.com return "%s" % Latency(self) 158410267SGeoffrey.Blake@arm.com 15853101Sstever@eecs.umich.edu def __getattr__(self, attr): 15863101Sstever@eecs.umich.edu if attr == 'frequency': 15873101Sstever@eecs.umich.edu return Frequency(self) 15883101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 15893101Sstever@eecs.umich.edu return Latency(self) 15903101Sstever@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 15913101Sstever@eecs.umich.edu 15924762Snate@binkert.org def getValue(self): 15934762Snate@binkert.org return self.period.getValue() 15944762Snate@binkert.org 159510380SAndrew.Bardsley@arm.com def config_value(self): 159610380SAndrew.Bardsley@arm.com return self.period.config_value() 159710380SAndrew.Bardsley@arm.com 15983101Sstever@eecs.umich.edu def ini_str(self): 15993101Sstever@eecs.umich.edu return self.period.ini_str() 16003101Sstever@eecs.umich.edu 16019827Sakash.bagdia@arm.comclass Voltage(float,ParamValue): 16029827Sakash.bagdia@arm.com cxx_type = 'double' 160310267SGeoffrey.Blake@arm.com ex_str = "1V" 160411498Sakash.bagdia@ARM.com cmd_line_settable = True 160510267SGeoffrey.Blake@arm.com 16069827Sakash.bagdia@arm.com def __new__(cls, value): 16079827Sakash.bagdia@arm.com # convert to voltage 16089827Sakash.bagdia@arm.com val = convert.toVoltage(value) 16099827Sakash.bagdia@arm.com return super(cls, Voltage).__new__(cls, val) 16109827Sakash.bagdia@arm.com 161110267SGeoffrey.Blake@arm.com def __call__(self, value): 161210267SGeoffrey.Blake@arm.com val = convert.toVoltage(value) 161310267SGeoffrey.Blake@arm.com self.__init__(val) 161410267SGeoffrey.Blake@arm.com return value 161510267SGeoffrey.Blake@arm.com 16169827Sakash.bagdia@arm.com def __str__(self): 161710267SGeoffrey.Blake@arm.com return str(self.getValue()) 16189827Sakash.bagdia@arm.com 16199827Sakash.bagdia@arm.com def getValue(self): 16209827Sakash.bagdia@arm.com value = float(self) 16219827Sakash.bagdia@arm.com return value 16229827Sakash.bagdia@arm.com 16239827Sakash.bagdia@arm.com def ini_str(self): 16249827Sakash.bagdia@arm.com return '%f' % self.getValue() 16259827Sakash.bagdia@arm.com 162610458Sandreas.hansson@arm.com @classmethod 162710458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 162810458Sandreas.hansson@arm.com code('#include <sstream>') 162910458Sandreas.hansson@arm.com 163010458Sandreas.hansson@arm.com @classmethod 163110458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 163210458Sandreas.hansson@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 163310458Sandreas.hansson@arm.com 163410427Sandreas.hansson@arm.comclass Current(float, ParamValue): 163510427Sandreas.hansson@arm.com cxx_type = 'double' 163610427Sandreas.hansson@arm.com ex_str = "1mA" 163710427Sandreas.hansson@arm.com cmd_line_settable = False 163810427Sandreas.hansson@arm.com 163910427Sandreas.hansson@arm.com def __new__(cls, value): 164010427Sandreas.hansson@arm.com # convert to current 164110427Sandreas.hansson@arm.com val = convert.toCurrent(value) 164210427Sandreas.hansson@arm.com return super(cls, Current).__new__(cls, val) 164310427Sandreas.hansson@arm.com 164410427Sandreas.hansson@arm.com def __call__(self, value): 164510427Sandreas.hansson@arm.com val = convert.toCurrent(value) 164610427Sandreas.hansson@arm.com self.__init__(val) 164710427Sandreas.hansson@arm.com return value 164810427Sandreas.hansson@arm.com 164910427Sandreas.hansson@arm.com def __str__(self): 165010427Sandreas.hansson@arm.com return str(self.getValue()) 165110427Sandreas.hansson@arm.com 165210427Sandreas.hansson@arm.com def getValue(self): 165310427Sandreas.hansson@arm.com value = float(self) 165410427Sandreas.hansson@arm.com return value 165510427Sandreas.hansson@arm.com 165610427Sandreas.hansson@arm.com def ini_str(self): 165710427Sandreas.hansson@arm.com return '%f' % self.getValue() 165810427Sandreas.hansson@arm.com 165910458Sandreas.hansson@arm.com @classmethod 166010458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 166110458Sandreas.hansson@arm.com code('#include <sstream>') 166210458Sandreas.hansson@arm.com 166310458Sandreas.hansson@arm.com @classmethod 166410458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 166510458Sandreas.hansson@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 166610458Sandreas.hansson@arm.com 16673101Sstever@eecs.umich.educlass NetworkBandwidth(float,ParamValue): 16683101Sstever@eecs.umich.edu cxx_type = 'float' 166910267SGeoffrey.Blake@arm.com ex_str = "1Gbps" 167010267SGeoffrey.Blake@arm.com cmd_line_settable = True 167110267SGeoffrey.Blake@arm.com 16723101Sstever@eecs.umich.edu def __new__(cls, value): 16734167Sbinkertn@umich.edu # convert to bits per second 16744167Sbinkertn@umich.edu val = convert.toNetworkBandwidth(value) 16753101Sstever@eecs.umich.edu return super(cls, NetworkBandwidth).__new__(cls, val) 16763101Sstever@eecs.umich.edu 16773101Sstever@eecs.umich.edu def __str__(self): 16783101Sstever@eecs.umich.edu return str(self.val) 16793101Sstever@eecs.umich.edu 168010267SGeoffrey.Blake@arm.com def __call__(self, value): 168110267SGeoffrey.Blake@arm.com val = convert.toNetworkBandwidth(value) 168210267SGeoffrey.Blake@arm.com self.__init__(val) 168310267SGeoffrey.Blake@arm.com return value 168410267SGeoffrey.Blake@arm.com 16854762Snate@binkert.org def getValue(self): 16864167Sbinkertn@umich.edu # convert to seconds per byte 16874167Sbinkertn@umich.edu value = 8.0 / float(self) 16884167Sbinkertn@umich.edu # convert to ticks per byte 16894762Snate@binkert.org value = ticks.fromSeconds(value) 16904762Snate@binkert.org return float(value) 16914762Snate@binkert.org 16924762Snate@binkert.org def ini_str(self): 16934762Snate@binkert.org return '%f' % self.getValue() 16943101Sstever@eecs.umich.edu 169510380SAndrew.Bardsley@arm.com def config_value(self): 169610380SAndrew.Bardsley@arm.com return '%f' % self.getValue() 169710380SAndrew.Bardsley@arm.com 169810458Sandreas.hansson@arm.com @classmethod 169910458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 170010458Sandreas.hansson@arm.com code('#include <sstream>') 170110458Sandreas.hansson@arm.com 170210458Sandreas.hansson@arm.com @classmethod 170310458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 170410458Sandreas.hansson@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 170510458Sandreas.hansson@arm.com 17063101Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue): 17073101Sstever@eecs.umich.edu cxx_type = 'float' 170810267SGeoffrey.Blake@arm.com ex_str = "1GB/s" 170910267SGeoffrey.Blake@arm.com cmd_line_settable = True 171010267SGeoffrey.Blake@arm.com 17115469Snate@binkert.org def __new__(cls, value): 17127743Sgblack@eecs.umich.edu # convert to bytes per second 17133102Sstever@eecs.umich.edu val = convert.toMemoryBandwidth(value) 17143101Sstever@eecs.umich.edu return super(cls, MemoryBandwidth).__new__(cls, val) 17153101Sstever@eecs.umich.edu 171610267SGeoffrey.Blake@arm.com def __call__(self, value): 171710267SGeoffrey.Blake@arm.com val = convert.toMemoryBandwidth(value) 171810267SGeoffrey.Blake@arm.com self.__init__(val) 171910267SGeoffrey.Blake@arm.com return value 17203101Sstever@eecs.umich.edu 17214762Snate@binkert.org def getValue(self): 17224167Sbinkertn@umich.edu # convert to seconds per byte 17235468Snate@binkert.org value = float(self) 17245468Snate@binkert.org if value: 17255468Snate@binkert.org value = 1.0 / float(self) 17264167Sbinkertn@umich.edu # convert to ticks per byte 17274762Snate@binkert.org value = ticks.fromSeconds(value) 17284762Snate@binkert.org return float(value) 17294762Snate@binkert.org 17304762Snate@binkert.org def ini_str(self): 17314762Snate@binkert.org return '%f' % self.getValue() 17323101Sstever@eecs.umich.edu 173310380SAndrew.Bardsley@arm.com def config_value(self): 173410380SAndrew.Bardsley@arm.com return '%f' % self.getValue() 173510380SAndrew.Bardsley@arm.com 173610458Sandreas.hansson@arm.com @classmethod 173710458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 173810458Sandreas.hansson@arm.com code('#include <sstream>') 173910458Sandreas.hansson@arm.com 174010458Sandreas.hansson@arm.com @classmethod 174110458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 174210458Sandreas.hansson@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 174310458Sandreas.hansson@arm.com 17443101Sstever@eecs.umich.edu# 17453101Sstever@eecs.umich.edu# "Constants"... handy aliases for various values. 17463101Sstever@eecs.umich.edu# 17473101Sstever@eecs.umich.edu 17483102Sstever@eecs.umich.edu# Special class for NULL pointers. Note the special check in 17493102Sstever@eecs.umich.edu# make_param_value() above that lets these be assigned where a 17503102Sstever@eecs.umich.edu# SimObject is required. 17513102Sstever@eecs.umich.edu# only one copy of a particular node 17523102Sstever@eecs.umich.educlass NullSimObject(object): 17533102Sstever@eecs.umich.edu __metaclass__ = Singleton 17543102Sstever@eecs.umich.edu 17553102Sstever@eecs.umich.edu def __call__(cls): 17563102Sstever@eecs.umich.edu return cls 17573102Sstever@eecs.umich.edu 17583102Sstever@eecs.umich.edu def _instantiate(self, parent = None, path = ''): 17593102Sstever@eecs.umich.edu pass 17603102Sstever@eecs.umich.edu 17613102Sstever@eecs.umich.edu def ini_str(self): 17623102Sstever@eecs.umich.edu return 'Null' 17633102Sstever@eecs.umich.edu 17643102Sstever@eecs.umich.edu def unproxy(self, base): 17653102Sstever@eecs.umich.edu return self 17663102Sstever@eecs.umich.edu 17673102Sstever@eecs.umich.edu def set_path(self, parent, name): 17683102Sstever@eecs.umich.edu pass 17694762Snate@binkert.org 17703102Sstever@eecs.umich.edu def __str__(self): 17713102Sstever@eecs.umich.edu return 'Null' 17723102Sstever@eecs.umich.edu 177310380SAndrew.Bardsley@arm.com def config_value(self): 177410380SAndrew.Bardsley@arm.com return None 177510380SAndrew.Bardsley@arm.com 17764762Snate@binkert.org def getValue(self): 17774762Snate@binkert.org return None 17784762Snate@binkert.org 17793102Sstever@eecs.umich.edu# The only instance you'll ever need... 17803102Sstever@eecs.umich.eduNULL = NullSimObject() 17813102Sstever@eecs.umich.edu 17823102Sstever@eecs.umich.edudef isNullPointer(value): 17833102Sstever@eecs.umich.edu return isinstance(value, NullSimObject) 17843102Sstever@eecs.umich.edu 17853101Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound. 17863101Sstever@eecs.umich.eduMaxAddr = Addr.max 17873101Sstever@eecs.umich.eduMaxTick = Tick.max 17883101Sstever@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr) 17893101Sstever@eecs.umich.edu 17903101Sstever@eecs.umich.edu 17913101Sstever@eecs.umich.edu##################################################################### 17923101Sstever@eecs.umich.edu# 17933101Sstever@eecs.umich.edu# Port objects 17943101Sstever@eecs.umich.edu# 17953101Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system. 17963101Sstever@eecs.umich.edu# 17973101Sstever@eecs.umich.edu##################################################################### 17983101Sstever@eecs.umich.edu 17993101Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a 18003101Sstever@eecs.umich.edu# particular SimObject. 18013101Sstever@eecs.umich.educlass PortRef(object): 18028839Sandreas.hansson@arm.com def __init__(self, simobj, name, role): 18033105Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 18043101Sstever@eecs.umich.edu self.simobj = simobj 18053101Sstever@eecs.umich.edu self.name = name 18068839Sandreas.hansson@arm.com self.role = role 18073101Sstever@eecs.umich.edu self.peer = None # not associated with another port yet 18083101Sstever@eecs.umich.edu self.ccConnected = False # C++ port connection done? 18093105Sstever@eecs.umich.edu self.index = -1 # always -1 for non-vector ports 18103101Sstever@eecs.umich.edu 18113103Sstever@eecs.umich.edu def __str__(self): 18123105Sstever@eecs.umich.edu return '%s.%s' % (self.simobj, self.name) 18133103Sstever@eecs.umich.edu 18148840Sandreas.hansson@arm.com def __len__(self): 18158840Sandreas.hansson@arm.com # Return the number of connected ports, i.e. 0 is we have no 18168840Sandreas.hansson@arm.com # peer and 1 if we do. 18178840Sandreas.hansson@arm.com return int(self.peer != None) 18188840Sandreas.hansson@arm.com 18193105Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 18203105Sstever@eecs.umich.edu def ini_str(self): 18213105Sstever@eecs.umich.edu return str(self.peer) 18223105Sstever@eecs.umich.edu 18239017Sandreas.hansson@arm.com # for config.json 18249017Sandreas.hansson@arm.com def get_config_as_dict(self): 18259017Sandreas.hansson@arm.com return {'role' : self.role, 'peer' : str(self.peer)} 18269017Sandreas.hansson@arm.com 18273105Sstever@eecs.umich.edu def __getattr__(self, attr): 18283105Sstever@eecs.umich.edu if attr == 'peerObj': 18293105Sstever@eecs.umich.edu # shorthand for proxies 18303105Sstever@eecs.umich.edu return self.peer.simobj 18313105Sstever@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 18323105Sstever@eecs.umich.edu (self.__class__.__name__, attr) 18333105Sstever@eecs.umich.edu 18343105Sstever@eecs.umich.edu # Full connection is symmetric (both ways). Called via 18353105Sstever@eecs.umich.edu # SimObject.__setattr__ as a result of a port assignment, e.g., 18363109Sstever@eecs.umich.edu # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 18373105Sstever@eecs.umich.edu # e.g., "obj1.portA[3] = obj2.portB". 18383105Sstever@eecs.umich.edu def connect(self, other): 18393105Sstever@eecs.umich.edu if isinstance(other, VectorPortRef): 18403105Sstever@eecs.umich.edu # reference to plain VectorPort is implicit append 18413105Sstever@eecs.umich.edu other = other._get_next() 18423105Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 18439014Sandreas.hansson@arm.com fatal("Port %s is already connected to %s, cannot connect %s\n", 18449014Sandreas.hansson@arm.com self, self.peer, other); 18453101Sstever@eecs.umich.edu self.peer = other 18463109Sstever@eecs.umich.edu if proxy.isproxy(other): 18473109Sstever@eecs.umich.edu other.set_param_desc(PortParamDesc()) 18483109Sstever@eecs.umich.edu elif isinstance(other, PortRef): 18493109Sstever@eecs.umich.edu if other.peer is not self: 18503109Sstever@eecs.umich.edu other.connect(self) 18513109Sstever@eecs.umich.edu else: 18523109Sstever@eecs.umich.edu raise TypeError, \ 18533109Sstever@eecs.umich.edu "assigning non-port reference '%s' to port '%s'" \ 18543109Sstever@eecs.umich.edu % (other, self) 18553101Sstever@eecs.umich.edu 185610355SGeoffrey.Blake@arm.com # Allow a master/slave port pair to be spliced between 185710355SGeoffrey.Blake@arm.com # a port and its connected peer. Useful operation for connecting 185810355SGeoffrey.Blake@arm.com # instrumentation structures into a system when it is necessary 185910355SGeoffrey.Blake@arm.com # to connect the instrumentation after the full system has been 186010355SGeoffrey.Blake@arm.com # constructed. 186110355SGeoffrey.Blake@arm.com def splice(self, new_master_peer, new_slave_peer): 186210355SGeoffrey.Blake@arm.com if self.peer and not proxy.isproxy(self.peer): 186310355SGeoffrey.Blake@arm.com if isinstance(new_master_peer, PortRef) and \ 186410355SGeoffrey.Blake@arm.com isinstance(new_slave_peer, PortRef): 186510355SGeoffrey.Blake@arm.com old_peer = self.peer 186610355SGeoffrey.Blake@arm.com if self.role == 'SLAVE': 186710355SGeoffrey.Blake@arm.com self.peer = new_master_peer 186810355SGeoffrey.Blake@arm.com old_peer.peer = new_slave_peer 186910355SGeoffrey.Blake@arm.com new_master_peer.connect(self) 187010355SGeoffrey.Blake@arm.com new_slave_peer.connect(old_peer) 187110355SGeoffrey.Blake@arm.com elif self.role == 'MASTER': 187210355SGeoffrey.Blake@arm.com self.peer = new_slave_peer 187310355SGeoffrey.Blake@arm.com old_peer.peer = new_master_peer 187410355SGeoffrey.Blake@arm.com new_slave_peer.connect(self) 187510355SGeoffrey.Blake@arm.com new_master_peer.connect(old_peer) 187610355SGeoffrey.Blake@arm.com else: 187710355SGeoffrey.Blake@arm.com panic("Port %s has unknown role, "+\ 187810355SGeoffrey.Blake@arm.com "cannot splice in new peers\n", self) 187910355SGeoffrey.Blake@arm.com else: 188010355SGeoffrey.Blake@arm.com raise TypeError, \ 188110355SGeoffrey.Blake@arm.com "Splicing non-port references '%s','%s' to port '%s'"\ 188210355SGeoffrey.Blake@arm.com % (new_peer, peers_new_peer, self) 188310355SGeoffrey.Blake@arm.com else: 188410355SGeoffrey.Blake@arm.com fatal("Port %s not connected, cannot splice in new peers\n", self) 188510355SGeoffrey.Blake@arm.com 18863105Sstever@eecs.umich.edu def clone(self, simobj, memo): 18873105Sstever@eecs.umich.edu if memo.has_key(self): 18883105Sstever@eecs.umich.edu return memo[self] 18893101Sstever@eecs.umich.edu newRef = copy.copy(self) 18903105Sstever@eecs.umich.edu memo[self] = newRef 18913105Sstever@eecs.umich.edu newRef.simobj = simobj 18923101Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 18933105Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 18943179Sstever@eecs.umich.edu peerObj = self.peer.simobj(_memo=memo) 18953105Sstever@eecs.umich.edu newRef.peer = self.peer.clone(peerObj, memo) 18963105Sstever@eecs.umich.edu assert(not isinstance(newRef.peer, VectorPortRef)) 18973101Sstever@eecs.umich.edu return newRef 18983101Sstever@eecs.umich.edu 18993105Sstever@eecs.umich.edu def unproxy(self, simobj): 19003105Sstever@eecs.umich.edu assert(simobj is self.simobj) 19013105Sstever@eecs.umich.edu if proxy.isproxy(self.peer): 19023105Sstever@eecs.umich.edu try: 19033105Sstever@eecs.umich.edu realPeer = self.peer.unproxy(self.simobj) 19043105Sstever@eecs.umich.edu except: 19053105Sstever@eecs.umich.edu print "Error in unproxying port '%s' of %s" % \ 19063105Sstever@eecs.umich.edu (self.name, self.simobj.path()) 19073105Sstever@eecs.umich.edu raise 19083105Sstever@eecs.umich.edu self.connect(realPeer) 19093105Sstever@eecs.umich.edu 19103101Sstever@eecs.umich.edu # Call C++ to create corresponding port connection between C++ objects 19113101Sstever@eecs.umich.edu def ccConnect(self): 191211802Sandreas.sandberg@arm.com from _m5.pyobject import connectPorts 19134762Snate@binkert.org 19148839Sandreas.hansson@arm.com if self.role == 'SLAVE': 19158839Sandreas.hansson@arm.com # do nothing and let the master take care of it 19168839Sandreas.hansson@arm.com return 19178839Sandreas.hansson@arm.com 19183101Sstever@eecs.umich.edu if self.ccConnected: # already done this 19193101Sstever@eecs.umich.edu return 19203101Sstever@eecs.umich.edu peer = self.peer 19215578SSteve.Reinhardt@amd.com if not self.peer: # nothing to connect to 19225578SSteve.Reinhardt@amd.com return 19238839Sandreas.hansson@arm.com 19248839Sandreas.hansson@arm.com # check that we connect a master to a slave 19258839Sandreas.hansson@arm.com if self.role == peer.role: 19268839Sandreas.hansson@arm.com raise TypeError, \ 19278839Sandreas.hansson@arm.com "cannot connect '%s' and '%s' due to identical role '%s'" \ 19288839Sandreas.hansson@arm.com % (peer, self, self.role) 19298839Sandreas.hansson@arm.com 19307526Ssteve.reinhardt@amd.com try: 19318839Sandreas.hansson@arm.com # self is always the master and peer the slave 19327526Ssteve.reinhardt@amd.com connectPorts(self.simobj.getCCObject(), self.name, self.index, 19337526Ssteve.reinhardt@amd.com peer.simobj.getCCObject(), peer.name, peer.index) 19347526Ssteve.reinhardt@amd.com except: 19357526Ssteve.reinhardt@amd.com print "Error connecting port %s.%s to %s.%s" % \ 19367526Ssteve.reinhardt@amd.com (self.simobj.path(), self.name, 19377526Ssteve.reinhardt@amd.com peer.simobj.path(), peer.name) 19387526Ssteve.reinhardt@amd.com raise 19393101Sstever@eecs.umich.edu self.ccConnected = True 19403101Sstever@eecs.umich.edu peer.ccConnected = True 19413101Sstever@eecs.umich.edu 19423105Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a 19433105Sstever@eecs.umich.edu# PortRef, but has an index. 19443105Sstever@eecs.umich.educlass VectorPortElementRef(PortRef): 19458839Sandreas.hansson@arm.com def __init__(self, simobj, name, role, index): 19468839Sandreas.hansson@arm.com PortRef.__init__(self, simobj, name, role) 19473105Sstever@eecs.umich.edu self.index = index 19483105Sstever@eecs.umich.edu 19493105Sstever@eecs.umich.edu def __str__(self): 19503105Sstever@eecs.umich.edu return '%s.%s[%d]' % (self.simobj, self.name, self.index) 19513105Sstever@eecs.umich.edu 19523105Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element). 19533105Sstever@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances. 19543105Sstever@eecs.umich.educlass VectorPortRef(object): 19558839Sandreas.hansson@arm.com def __init__(self, simobj, name, role): 19563105Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 19573105Sstever@eecs.umich.edu self.simobj = simobj 19583105Sstever@eecs.umich.edu self.name = name 19598839Sandreas.hansson@arm.com self.role = role 19603105Sstever@eecs.umich.edu self.elements = [] 19613105Sstever@eecs.umich.edu 19623109Sstever@eecs.umich.edu def __str__(self): 19633109Sstever@eecs.umich.edu return '%s.%s[:]' % (self.simobj, self.name) 19643109Sstever@eecs.umich.edu 19658840Sandreas.hansson@arm.com def __len__(self): 19668840Sandreas.hansson@arm.com # Return the number of connected peers, corresponding the the 19678840Sandreas.hansson@arm.com # length of the elements. 19688840Sandreas.hansson@arm.com return len(self.elements) 19698840Sandreas.hansson@arm.com 19703105Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 19713105Sstever@eecs.umich.edu def ini_str(self): 19723105Sstever@eecs.umich.edu return ' '.join([el.ini_str() for el in self.elements]) 19733105Sstever@eecs.umich.edu 19749017Sandreas.hansson@arm.com # for config.json 19759017Sandreas.hansson@arm.com def get_config_as_dict(self): 19769017Sandreas.hansson@arm.com return {'role' : self.role, 19779017Sandreas.hansson@arm.com 'peer' : [el.ini_str() for el in self.elements]} 19789017Sandreas.hansson@arm.com 19793105Sstever@eecs.umich.edu def __getitem__(self, key): 19803105Sstever@eecs.umich.edu if not isinstance(key, int): 19813105Sstever@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 19823105Sstever@eecs.umich.edu if key >= len(self.elements): 19833105Sstever@eecs.umich.edu # need to extend list 19848839Sandreas.hansson@arm.com ext = [VectorPortElementRef(self.simobj, self.name, self.role, i) 19853105Sstever@eecs.umich.edu for i in range(len(self.elements), key+1)] 19863105Sstever@eecs.umich.edu self.elements.extend(ext) 19873105Sstever@eecs.umich.edu return self.elements[key] 19883105Sstever@eecs.umich.edu 19893105Sstever@eecs.umich.edu def _get_next(self): 19903105Sstever@eecs.umich.edu return self[len(self.elements)] 19913105Sstever@eecs.umich.edu 19923105Sstever@eecs.umich.edu def __setitem__(self, key, value): 19933105Sstever@eecs.umich.edu if not isinstance(key, int): 19943105Sstever@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 19953105Sstever@eecs.umich.edu self[key].connect(value) 19963105Sstever@eecs.umich.edu 19973105Sstever@eecs.umich.edu def connect(self, other): 19983109Sstever@eecs.umich.edu if isinstance(other, (list, tuple)): 19993109Sstever@eecs.umich.edu # Assign list of port refs to vector port. 20003109Sstever@eecs.umich.edu # For now, append them... not sure if that's the right semantics 20013109Sstever@eecs.umich.edu # or if it should replace the current vector. 20023109Sstever@eecs.umich.edu for ref in other: 20033109Sstever@eecs.umich.edu self._get_next().connect(ref) 20043109Sstever@eecs.umich.edu else: 20053109Sstever@eecs.umich.edu # scalar assignment to plain VectorPort is implicit append 20063109Sstever@eecs.umich.edu self._get_next().connect(other) 20073109Sstever@eecs.umich.edu 20083109Sstever@eecs.umich.edu def clone(self, simobj, memo): 20093109Sstever@eecs.umich.edu if memo.has_key(self): 20103109Sstever@eecs.umich.edu return memo[self] 20113109Sstever@eecs.umich.edu newRef = copy.copy(self) 20123109Sstever@eecs.umich.edu memo[self] = newRef 20133109Sstever@eecs.umich.edu newRef.simobj = simobj 20143109Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 20153109Sstever@eecs.umich.edu newRef.elements = [el.clone(simobj, memo) for el in self.elements] 20163109Sstever@eecs.umich.edu return newRef 20173105Sstever@eecs.umich.edu 20183105Sstever@eecs.umich.edu def unproxy(self, simobj): 20193105Sstever@eecs.umich.edu [el.unproxy(simobj) for el in self.elements] 20203105Sstever@eecs.umich.edu 20213105Sstever@eecs.umich.edu def ccConnect(self): 20223105Sstever@eecs.umich.edu [el.ccConnect() for el in self.elements] 20233105Sstever@eecs.umich.edu 20243101Sstever@eecs.umich.edu# Port description object. Like a ParamDesc object, this represents a 20253101Sstever@eecs.umich.edu# logical port in the SimObject class, not a particular port on a 20263101Sstever@eecs.umich.edu# SimObject instance. The latter are represented by PortRef objects. 20273101Sstever@eecs.umich.educlass Port(object): 20283101Sstever@eecs.umich.edu # Generate a PortRef for this port on the given SimObject with the 20293101Sstever@eecs.umich.edu # given name 20303105Sstever@eecs.umich.edu def makeRef(self, simobj): 20318839Sandreas.hansson@arm.com return PortRef(simobj, self.name, self.role) 20323101Sstever@eecs.umich.edu 20333101Sstever@eecs.umich.edu # Connect an instance of this port (on the given SimObject with 20343101Sstever@eecs.umich.edu # the given name) with the port described by the supplied PortRef 20353105Sstever@eecs.umich.edu def connect(self, simobj, ref): 20363105Sstever@eecs.umich.edu self.makeRef(simobj).connect(ref) 20373101Sstever@eecs.umich.edu 20388840Sandreas.hansson@arm.com # No need for any pre-declarations at the moment as we merely rely 20398840Sandreas.hansson@arm.com # on an unsigned int. 20408840Sandreas.hansson@arm.com def cxx_predecls(self, code): 20418840Sandreas.hansson@arm.com pass 20428840Sandreas.hansson@arm.com 20438840Sandreas.hansson@arm.com # Declare an unsigned int with the same name as the port, that 20448840Sandreas.hansson@arm.com # will eventually hold the number of connected ports (and thus the 20458840Sandreas.hansson@arm.com # number of elements for a VectorPort). 20468840Sandreas.hansson@arm.com def cxx_decl(self, code): 20478840Sandreas.hansson@arm.com code('unsigned int port_${{self.name}}_connection_count;') 20488840Sandreas.hansson@arm.com 20498839Sandreas.hansson@arm.comclass MasterPort(Port): 20508839Sandreas.hansson@arm.com # MasterPort("description") 20518839Sandreas.hansson@arm.com def __init__(self, *args): 20528839Sandreas.hansson@arm.com if len(args) == 1: 20538839Sandreas.hansson@arm.com self.desc = args[0] 20548839Sandreas.hansson@arm.com self.role = 'MASTER' 20558839Sandreas.hansson@arm.com else: 20568839Sandreas.hansson@arm.com raise TypeError, 'wrong number of arguments' 20578839Sandreas.hansson@arm.com 20588839Sandreas.hansson@arm.comclass SlavePort(Port): 20598839Sandreas.hansson@arm.com # SlavePort("description") 20608839Sandreas.hansson@arm.com def __init__(self, *args): 20618839Sandreas.hansson@arm.com if len(args) == 1: 20628839Sandreas.hansson@arm.com self.desc = args[0] 20638839Sandreas.hansson@arm.com self.role = 'SLAVE' 20648839Sandreas.hansson@arm.com else: 20658839Sandreas.hansson@arm.com raise TypeError, 'wrong number of arguments' 20668839Sandreas.hansson@arm.com 20673101Sstever@eecs.umich.edu# VectorPort description object. Like Port, but represents a vector 206810405Sandreas.hansson@arm.com# of connections (e.g., as on a XBar). 20693101Sstever@eecs.umich.educlass VectorPort(Port): 20703105Sstever@eecs.umich.edu def __init__(self, *args): 20713101Sstever@eecs.umich.edu self.isVec = True 20723101Sstever@eecs.umich.edu 20733105Sstever@eecs.umich.edu def makeRef(self, simobj): 20748839Sandreas.hansson@arm.com return VectorPortRef(simobj, self.name, self.role) 20758839Sandreas.hansson@arm.com 20768839Sandreas.hansson@arm.comclass VectorMasterPort(VectorPort): 20778839Sandreas.hansson@arm.com # VectorMasterPort("description") 20788839Sandreas.hansson@arm.com def __init__(self, *args): 20798839Sandreas.hansson@arm.com if len(args) == 1: 20808839Sandreas.hansson@arm.com self.desc = args[0] 20818839Sandreas.hansson@arm.com self.role = 'MASTER' 20828839Sandreas.hansson@arm.com VectorPort.__init__(self, *args) 20838839Sandreas.hansson@arm.com else: 20848839Sandreas.hansson@arm.com raise TypeError, 'wrong number of arguments' 20858839Sandreas.hansson@arm.com 20868839Sandreas.hansson@arm.comclass VectorSlavePort(VectorPort): 20878839Sandreas.hansson@arm.com # VectorSlavePort("description") 20888839Sandreas.hansson@arm.com def __init__(self, *args): 20898839Sandreas.hansson@arm.com if len(args) == 1: 20908839Sandreas.hansson@arm.com self.desc = args[0] 20918839Sandreas.hansson@arm.com self.role = 'SLAVE' 20928839Sandreas.hansson@arm.com VectorPort.__init__(self, *args) 20938839Sandreas.hansson@arm.com else: 20948839Sandreas.hansson@arm.com raise TypeError, 'wrong number of arguments' 20953105Sstever@eecs.umich.edu 20963109Sstever@eecs.umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 20973109Sstever@eecs.umich.edu# proxy objects (via set_param_desc()) so that proxy error messages 20983109Sstever@eecs.umich.edu# make sense. 20993109Sstever@eecs.umich.educlass PortParamDesc(object): 21003109Sstever@eecs.umich.edu __metaclass__ = Singleton 21013109Sstever@eecs.umich.edu 21023109Sstever@eecs.umich.edu ptype_str = 'Port' 21033109Sstever@eecs.umich.edu ptype = Port 21043105Sstever@eecs.umich.edu 21056654Snate@binkert.orgbaseEnums = allEnums.copy() 21066654Snate@binkert.orgbaseParams = allParams.copy() 21076654Snate@binkert.org 21086654Snate@binkert.orgdef clear(): 21096654Snate@binkert.org global allEnums, allParams 21106654Snate@binkert.org 21116654Snate@binkert.org allEnums = baseEnums.copy() 21126654Snate@binkert.org allParams = baseParams.copy() 21136654Snate@binkert.org 21143101Sstever@eecs.umich.edu__all__ = ['Param', 'VectorParam', 21153101Sstever@eecs.umich.edu 'Enum', 'Bool', 'String', 'Float', 21163101Sstever@eecs.umich.edu 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 21173101Sstever@eecs.umich.edu 'Int32', 'UInt32', 'Int64', 'UInt64', 21183101Sstever@eecs.umich.edu 'Counter', 'Addr', 'Tick', 'Percent', 21193101Sstever@eecs.umich.edu 'TcpPort', 'UdpPort', 'EthernetAddr', 21207777Sgblack@eecs.umich.edu 'IpAddress', 'IpNetmask', 'IpWithPort', 21213101Sstever@eecs.umich.edu 'MemorySize', 'MemorySize32', 21229827Sakash.bagdia@arm.com 'Latency', 'Frequency', 'Clock', 'Voltage', 21233101Sstever@eecs.umich.edu 'NetworkBandwidth', 'MemoryBandwidth', 21249232Sandreas.hansson@arm.com 'AddrRange', 21253101Sstever@eecs.umich.edu 'MaxAddr', 'MaxTick', 'AllMemory', 21263885Sbinkertn@umich.edu 'Time', 21273102Sstever@eecs.umich.edu 'NextEthernetAddr', 'NULL', 21288839Sandreas.hansson@arm.com 'MasterPort', 'SlavePort', 21298839Sandreas.hansson@arm.com 'VectorMasterPort', 'VectorSlavePort'] 21306654Snate@binkert.org 21316654Snate@binkert.orgimport SimObject 2132