params.py revision 10676:f6c168692b20
111988Sandreas.sandberg@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 10511988Sandreas.sandberg@arm.com # Generate the code needed as a prerequisite for including a 10611988Sandreas.sandberg@arm.com # reference to a C++ object of this type in a SWIG .i file. 10711988Sandreas.sandberg@arm.com # Typically generates one or more %import or %include statements. 10811988Sandreas.sandberg@arm.com @classmethod 1093101Sstever@eecs.umich.edu def swig_predecls(cls, code): 1103101Sstever@eecs.umich.edu 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 11410380SAndrew.Bardsley@arm.com def ini_str(self): 11510380SAndrew.Bardsley@arm.com return str(self) 11610380SAndrew.Bardsley@arm.com 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 12010458Sandreas.hansson@arm.com def config_value(self): 12110458Sandreas.hansson@arm.com return str(self) 12210458Sandreas.hansson@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): 1323101Sstever@eecs.umich.edu code('// Unhandled param type: %s' % cls.__name__) 1333101Sstever@eecs.umich.edu code('%s false;' % ret) 1343101Sstever@eecs.umich.edu 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 13710267SGeoffrey.Blake@arm.com def unproxy(self, base): 13810267SGeoffrey.Blake@arm.com return self 13910267SGeoffrey.Blake@arm.com 14010267SGeoffrey.Blake@arm.com # Produce a human readable version of the stored value 1413101Sstever@eecs.umich.edu def pretty_print(self, value): 1423101Sstever@eecs.umich.edu return str(value) 1433101Sstever@eecs.umich.edu 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' 1765033Smilesck@eecs.umich.edu 1776656Snate@binkert.org def __getattr__(self, attr): 1785033Smilesck@eecs.umich.edu if attr == 'ptype': 1795033Smilesck@eecs.umich.edu ptype = SimObject.allClasses[self.ptype_str] 1805033Smilesck@eecs.umich.edu assert isSimObjectClass(ptype) 1813101Sstever@eecs.umich.edu self.ptype = ptype 1823101Sstever@eecs.umich.edu return ptype 1833101Sstever@eecs.umich.edu 18410267SGeoffrey.Blake@arm.com raise AttributeError, "'%s' object has no attribute '%s'" % \ 18510267SGeoffrey.Blake@arm.com (type(self).__name__, attr) 18610267SGeoffrey.Blake@arm.com 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 1973101Sstever@eecs.umich.edu else: 1983101Sstever@eecs.umich.edu return False 1993101Sstever@eecs.umich.edu 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 2073102Sstever@eecs.umich.edu return value 2083101Sstever@eecs.umich.edu if isinstance(value, self.ptype): 2093101Sstever@eecs.umich.edu return value 2103101Sstever@eecs.umich.edu if isNullPointer(value) and isSimObjectClass(self.ptype): 21110267SGeoffrey.Blake@arm.com return value 21210267SGeoffrey.Blake@arm.com return self.ptype(value) 21310267SGeoffrey.Blake@arm.com 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): 2187673Snate@binkert.org return NULL 2198607Sgblack@eecs.umich.edu return self.ptype(value).pretty_print(value) 2207673Snate@binkert.org 2213101Sstever@eecs.umich.edu def cxx_predecls(self, code): 22211988Sandreas.sandberg@arm.com code('#include <cstddef>') 22311988Sandreas.sandberg@arm.com self.ptype.cxx_predecls(code) 22411988Sandreas.sandberg@arm.com 2257673Snate@binkert.org def swig_predecls(self, code): 2267673Snate@binkert.org self.ptype.swig_predecls(code) 2273101Sstever@eecs.umich.edu 2283101Sstever@eecs.umich.edu def cxx_decl(self, code): 2293101Sstever@eecs.umich.edu 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 2335033Smilesck@eecs.umich.edu# single value. 2345475Snate@binkert.org 2355475Snate@binkert.orgclass VectorParamValue(list): 2365475Snate@binkert.org __metaclass__ = MetaParamValue 2375475Snate@binkert.org def __setattr__(self, attr, value): 23810380SAndrew.Bardsley@arm.com raise AttributeError, \ 23910380SAndrew.Bardsley@arm.com "Not allowed to set %s on '%s'" % (attr, type(self).__name__) 24010380SAndrew.Bardsley@arm.com 2413101Sstever@eecs.umich.edu def config_value(self): 2423101Sstever@eecs.umich.edu return [v.config_value() for v in self] 2433101Sstever@eecs.umich.edu 2444762Snate@binkert.org def ini_str(self): 2454762Snate@binkert.org return ' '.join([v.ini_str() for v in self]) 2464762Snate@binkert.org 2473101Sstever@eecs.umich.edu def getValue(self): 24812050Snikos.nikoleris@arm.com return [ v.getValue() for v in self ] 24912050Snikos.nikoleris@arm.com 25012050Snikos.nikoleris@arm.com def unproxy(self, base): 2518459SAli.Saidi@ARM.com if len(self) == 1 and isinstance(self[0], proxy.AllProxy): 2528459SAli.Saidi@ARM.com return self[0].unproxy(base) 25312050Snikos.nikoleris@arm.com else: 2543101Sstever@eecs.umich.edu return [v.unproxy(base) for v in self] 2557528Ssteve.reinhardt@amd.com 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 2613101Sstever@eecs.umich.edu def clear_parent(self, old_parent): 2627528Ssteve.reinhardt@amd.com 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)) 2728321Ssteve.reinhardt@amd.com 27312194Sgabeblack@google.com def has_parent(self): 2747528Ssteve.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(): 2873101Sstever@eecs.umich.edu yield obj 2888664SAli.Saidi@ARM.com 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 2949953Sgeoffrey.blake@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) 30710267SGeoffrey.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 3273101Sstever@eecs.umich.edu 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 33410364SGeoffrey.Blake@arm.com 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) \ 3383101Sstever@eecs.umich.edu for v in value.strip('[').strip(']').split(',') ] 3394762Snate@binkert.org else: 3404762Snate@binkert.org # singleton: coerce to a single-element list 3414762Snate@binkert.org tmp_list = [ ParamDesc.convert(self, value) ] 3424762Snate@binkert.org 3437528Ssteve.reinhardt@amd.com if isSimObjectSequence(tmp_list): 3444762Snate@binkert.org return SimObjectVector(tmp_list) 3454762Snate@binkert.org else: 3464762Snate@binkert.org return VectorParamValue(tmp_list) 34710267SGeoffrey.Blake@arm.com 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): 37310364SGeoffrey.Blake@arm.com # If input is a csv string 37410364SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) \ 37510267SGeoffrey.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) 3817673Snate@binkert.org 3827673Snate@binkert.org def swig_module_name(self): 3837673Snate@binkert.org return "%s_vector" % self.ptype_str 3843101Sstever@eecs.umich.edu 38511988Sandreas.sandberg@arm.com def swig_predecls(self, code): 38611988Sandreas.sandberg@arm.com code('%import "${{self.swig_module_name()}}.i"') 38711988Sandreas.sandberg@arm.com 38811988Sandreas.sandberg@arm.com def swig_decl(self, code): 3897673Snate@binkert.org code('%module(package="m5.internal") ${{self.swig_module_name()}}') 3907673Snate@binkert.org code('%{') 3913101Sstever@eecs.umich.edu self.ptype.cxx_predecls(code) 3923101Sstever@eecs.umich.edu code('%}') 3933101Sstever@eecs.umich.edu code() 3943101Sstever@eecs.umich.edu # Make sure the SWIGPY_SLICE_ARG is defined through this inclusion 3953101Sstever@eecs.umich.edu code('%include "std_container.i"') 3963101Sstever@eecs.umich.edu code() 3973101Sstever@eecs.umich.edu self.ptype.swig_predecls(code) 3983101Sstever@eecs.umich.edu code() 3993101Sstever@eecs.umich.edu code('%include "std_vector.i"') 4003101Sstever@eecs.umich.edu code() 4013101Sstever@eecs.umich.edu 4023101Sstever@eecs.umich.edu ptype = self.ptype_str 4033101Sstever@eecs.umich.edu cxx_type = self.ptype.cxx_type 4043101Sstever@eecs.umich.edu 4053101Sstever@eecs.umich.edu code('%template(vector_$ptype) std::vector< $cxx_type >;') 4065033Smilesck@eecs.umich.edu 4075033Smilesck@eecs.umich.edu def cxx_predecls(self, code): 4083101Sstever@eecs.umich.edu code('#include <vector>') 4093101Sstever@eecs.umich.edu self.ptype.cxx_predecls(code) 4103101Sstever@eecs.umich.edu 4113101Sstever@eecs.umich.edu def cxx_decl(self, code): 4123101Sstever@eecs.umich.edu 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: 4283101Sstever@eecs.umich.edu ptype = allParams[self.ptype_str] 4293101Sstever@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 43310267SGeoffrey.Blake@arm.com return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 4347673Snate@binkert.org 4357673Snate@binkert.orgParam = ParamFactory(ParamDesc) 4367673Snate@binkert.orgVectorParam = ParamFactory(VectorParamDesc) 4377673Snate@binkert.org 4387673Snate@binkert.org##################################################################### 43910267SGeoffrey.Blake@arm.com# 44010267SGeoffrey.Blake@arm.com# Parameter Types 44110267SGeoffrey.Blake@arm.com# 44210267SGeoffrey.Blake@arm.com# Though native Python types could be used to specify parameter types 44310458Sandreas.hansson@arm.com# (the 'ptype' field of the Param and VectorParam classes), it's more 44410458Sandreas.hansson@arm.com# flexible to define our own set of types. This gives us more control 44510458Sandreas.hansson@arm.com# over how Python expressions are converted to values (via the 44610458Sandreas.hansson@arm.com# __init__() constructor) and how these values are printed out (via 44710458Sandreas.hansson@arm.com# the __str__() conversion method). 4484762Snate@binkert.org# 4494762Snate@binkert.org##################################################################### 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' 4553101Sstever@eecs.umich.edu cmd_line_settable = True 4563101Sstever@eecs.umich.edu 4573101Sstever@eecs.umich.edu @classmethod 4583101Sstever@eecs.umich.edu def cxx_predecls(self, code): 4593101Sstever@eecs.umich.edu code('#include <string>') 4603101Sstever@eecs.umich.edu 4613714Sstever@eecs.umich.edu @classmethod 4623714Sstever@eecs.umich.edu def swig_predecls(cls, code): 4633714Sstever@eecs.umich.edu code('%include "std_string.i"') 4643714Sstever@eecs.umich.edu 4653714Sstever@eecs.umich.edu def __call__(self, value): 4663714Sstever@eecs.umich.edu self = value 4673101Sstever@eecs.umich.edu return value 4683101Sstever@eecs.umich.edu 4693101Sstever@eecs.umich.edu @classmethod 4703101Sstever@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 4713101Sstever@eecs.umich.edu code('%s = %s;' % (dest, src)) 4723101Sstever@eecs.umich.edu code('%s true;' % ret) 4733101Sstever@eecs.umich.edu 4743101Sstever@eecs.umich.edu def getValue(self): 4753101Sstever@eecs.umich.edu 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 4873101Sstever@eecs.umich.edu def __long__(self): 4883101Sstever@eecs.umich.edu return long(self.value) 4893101Sstever@eecs.umich.edu 4903101Sstever@eecs.umich.edu def __int__(self): 49110380SAndrew.Bardsley@arm.com return int(self.value) 49210380SAndrew.Bardsley@arm.com 49310380SAndrew.Bardsley@arm.com # hook for bounds checking 49410458Sandreas.hansson@arm.com def _check(self): 49510458Sandreas.hansson@arm.com return 49610458Sandreas.hansson@arm.com 49710458Sandreas.hansson@arm.com def __mul__(self, other): 49810458Sandreas.hansson@arm.com newobj = self.__class__(self) 49910458Sandreas.hansson@arm.com newobj.value *= other 50010458Sandreas.hansson@arm.com newobj._check() 50110458Sandreas.hansson@arm.com return newobj 50210458Sandreas.hansson@arm.com 50310458Sandreas.hansson@arm.com __rmul__ = __mul__ 50410458Sandreas.hansson@arm.com 50510458Sandreas.hansson@arm.com def __div__(self, other): 50610458Sandreas.hansson@arm.com newobj = self.__class__(self) 5073101Sstever@eecs.umich.edu newobj.value /= other 5085033Smilesck@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 5173101Sstever@eecs.umich.edu def config_value(self): 5183101Sstever@eecs.umich.edu return self.value 5193101Sstever@eecs.umich.edu 5203101Sstever@eecs.umich.edu @classmethod 5215822Ssaidi@eecs.umich.edu def cxx_ini_predecls(cls, code): 5225822Ssaidi@eecs.umich.edu # Assume that base/str.hh will be included anyway 5233101Sstever@eecs.umich.edu # code('#include "base/str.hh"') 5243101Sstever@eecs.umich.edu pass 5253101Sstever@eecs.umich.edu 5263101Sstever@eecs.umich.edu # The default for parsing PODs from an .ini entry is to extract from an 5273101Sstever@eecs.umich.edu # istringstream and let overloading choose the right type according to 5283101Sstever@eecs.umich.edu # the dest type. 5293101Sstever@eecs.umich.edu @classmethod 5303101Sstever@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 5313101Sstever@eecs.umich.edu code('%s to_number(%s, %s);' % (ret, src, dest)) 5323101Sstever@eecs.umich.edu 5333101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters. See CheckedInt. 5343101Sstever@eecs.umich.educlass CheckedIntType(MetaParamValue): 5353101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 53610267SGeoffrey.Blake@arm.com 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')): 5453102Sstever@eecs.umich.edu if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 5463714Sstever@eecs.umich.edu panic("CheckedInt subclass %s must define either\n" \ 5473101Sstever@eecs.umich.edu " 'min' and 'max' or 'size' and 'unsigned'\n", 5483714Sstever@eecs.umich.edu name); 5493714Sstever@eecs.umich.edu if cls.unsigned: 5503714Sstever@eecs.umich.edu cls.min = 0 5513101Sstever@eecs.umich.edu cls.max = 2 ** cls.size - 1 5523101Sstever@eecs.umich.edu else: 55310267SGeoffrey.Blake@arm.com cls.min = -(2 ** (cls.size - 1)) 55410267SGeoffrey.Blake@arm.com cls.max = (2 ** (cls.size - 1)) - 1 55510267SGeoffrey.Blake@arm.com 55610267SGeoffrey.Blake@arm.com# Abstract superclass for bounds-checked integer parameters. This 5577673Snate@binkert.org# class is subclassed to generate parameter classes with specific 5587673Snate@binkert.org# bounds. Initialization of the min and max bounds is done in the 5597673Snate@binkert.org# metaclass CheckedIntType.__init__. 5607673Snate@binkert.orgclass CheckedInt(NumericParamValue): 5617673Snate@binkert.org __metaclass__ = CheckedIntType 5624762Snate@binkert.org cmd_line_settable = True 5634762Snate@binkert.org 5644762Snate@binkert.org 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): 5713101Sstever@eecs.umich.edu self.value = convert.toInteger(value) 5723101Sstever@eecs.umich.edu elif isinstance(value, (int, long, float, NumericParamValue)): 5733101Sstever@eecs.umich.edu self.value = long(value) 5743101Sstever@eecs.umich.edu else: 5753101Sstever@eecs.umich.edu raise TypeError, "Can't convert object of type %s to CheckedInt" \ 5763101Sstever@eecs.umich.edu % type(value).__name__ 5773101Sstever@eecs.umich.edu self._check() 5783101Sstever@eecs.umich.edu 5793101Sstever@eecs.umich.edu def __call__(self, value): 5803101Sstever@eecs.umich.edu self.__init__(value) 5813101Sstever@eecs.umich.edu return value 5823101Sstever@eecs.umich.edu 5833101Sstever@eecs.umich.edu @classmethod 5849184Sandreas.hansson@arm.com def cxx_predecls(cls, code): 5859184Sandreas.hansson@arm.com # most derived types require this, so we just do it here once 5869184Sandreas.hansson@arm.com code('#include "base/types.hh"') 5879184Sandreas.hansson@arm.com 5889184Sandreas.hansson@arm.com @classmethod 5899184Sandreas.hansson@arm.com def swig_predecls(cls, code): 59011802Sandreas.sandberg@arm.com # most derived types require this, so we just do it here once 5919184Sandreas.hansson@arm.com code('%import "stdint.i"') 5929184Sandreas.hansson@arm.com code('%import "base/types.hh"') 59310458Sandreas.hansson@arm.com 59410458Sandreas.hansson@arm.com def getValue(self): 59510458Sandreas.hansson@arm.com return long(self.value) 59610458Sandreas.hansson@arm.com 59710458Sandreas.hansson@arm.comclass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 59810458Sandreas.hansson@arm.comclass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 59910458Sandreas.hansson@arm.com 60010458Sandreas.hansson@arm.comclass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 60110458Sandreas.hansson@arm.comclass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 60210458Sandreas.hansson@arm.comclass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 60310458Sandreas.hansson@arm.comclass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 60410458Sandreas.hansson@arm.comclass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 60510458Sandreas.hansson@arm.comclass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 60610458Sandreas.hansson@arm.comclass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 6073101Sstever@eecs.umich.educlass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 6084446Sbinkertn@umich.edu 60910668SGeoffrey.Blake@arm.comclass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 6103101Sstever@eecs.umich.educlass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 6115468Snate@binkert.orgclass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 61210267SGeoffrey.Blake@arm.comclass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 6135468Snate@binkert.org 6145468Snate@binkert.orgclass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 6155468Snate@binkert.org 6165468Snate@binkert.orgclass Cycles(CheckedInt): 6175468Snate@binkert.org cxx_type = 'Cycles' 61810267SGeoffrey.Blake@arm.com size = 64 61910267SGeoffrey.Blake@arm.com unsigned = True 62010267SGeoffrey.Blake@arm.com 62110267SGeoffrey.Blake@arm.com def getValue(self): 6224762Snate@binkert.org from m5.internal.core import Cycles 6234762Snate@binkert.org return Cycles(self.value) 6244762Snate@binkert.org 62510380SAndrew.Bardsley@arm.com @classmethod 62610380SAndrew.Bardsley@arm.com def cxx_ini_predecls(cls, code): 62710380SAndrew.Bardsley@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)') 6363101Sstever@eecs.umich.edu code(' %s = Cycles(_temp);' % dest) 6373101Sstever@eecs.umich.edu code('%s _ret;' % ret) 63810267SGeoffrey.Blake@arm.com 6393101Sstever@eecs.umich.educlass Float(ParamValue, float): 6403101Sstever@eecs.umich.edu cxx_type = 'double' 6413101Sstever@eecs.umich.edu cmd_line_settable = True 6423101Sstever@eecs.umich.edu 6433101Sstever@eecs.umich.edu def __init__(self, value): 6443101Sstever@eecs.umich.edu if isinstance(value, (int, long, float, NumericParamValue, Float, str)): 6453102Sstever@eecs.umich.edu self.value = float(value) 6463101Sstever@eecs.umich.edu else: 6473101Sstever@eecs.umich.edu raise TypeError, "Can't convert object of type %s to Float" \ 6483101Sstever@eecs.umich.edu % type(value).__name__ 6494168Sbinkertn@umich.edu 65010267SGeoffrey.Blake@arm.com def __call__(self, value): 6513101Sstever@eecs.umich.edu self.__init__(value) 6523101Sstever@eecs.umich.edu return value 6533101Sstever@eecs.umich.edu 6543101Sstever@eecs.umich.edu def getValue(self): 6553101Sstever@eecs.umich.edu return float(self.value) 6563101Sstever@eecs.umich.edu 6573102Sstever@eecs.umich.edu def config_value(self): 6583101Sstever@eecs.umich.edu return self 6593101Sstever@eecs.umich.edu 6603101Sstever@eecs.umich.edu @classmethod 6613101Sstever@eecs.umich.edu def cxx_ini_predecls(cls, code): 6623101Sstever@eecs.umich.edu code('#include <sstream>') 6633101Sstever@eecs.umich.edu 6643101Sstever@eecs.umich.edu @classmethod 6653101Sstever@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 6663101Sstever@eecs.umich.edu code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 6673101Sstever@eecs.umich.edu 6683101Sstever@eecs.umich.educlass MemorySize(CheckedInt): 66910317Smitch.hayenga@arm.com cxx_type = 'uint64_t' 67010317Smitch.hayenga@arm.com ex_str = '512MB' 67110317Smitch.hayenga@arm.com size = 64 67210317Smitch.hayenga@arm.com unsigned = True 67310317Smitch.hayenga@arm.com def __init__(self, value): 6743102Sstever@eecs.umich.edu if isinstance(value, MemorySize): 67510317Smitch.hayenga@arm.com self.value = value.value 67610317Smitch.hayenga@arm.com else: 67710317Smitch.hayenga@arm.com self.value = convert.toMemorySize(value) 67810317Smitch.hayenga@arm.com self._check() 67910317Smitch.hayenga@arm.com 6803101Sstever@eecs.umich.educlass MemorySize32(CheckedInt): 6813584Ssaidi@eecs.umich.edu cxx_type = 'uint32_t' 6823584Ssaidi@eecs.umich.edu ex_str = '512MB' 6833584Ssaidi@eecs.umich.edu size = 32 6843584Ssaidi@eecs.umich.edu unsigned = True 6853584Ssaidi@eecs.umich.edu def __init__(self, value): 68610267SGeoffrey.Blake@arm.com if isinstance(value, MemorySize): 68710267SGeoffrey.Blake@arm.com self.value = value.value 68810267SGeoffrey.Blake@arm.com else: 68910267SGeoffrey.Blake@arm.com self.value = convert.toMemorySize(value) 69010267SGeoffrey.Blake@arm.com self._check() 69110267SGeoffrey.Blake@arm.com 6923101Sstever@eecs.umich.educlass Addr(CheckedInt): 6939232Sandreas.hansson@arm.com cxx_type = 'Addr' 6949235Sandreas.hansson@arm.com size = 64 6953101Sstever@eecs.umich.edu unsigned = True 6963101Sstever@eecs.umich.edu def __init__(self, value): 69710676Sandreas.hansson@arm.com if isinstance(value, Addr): 6989411Sandreas.hansson@arm.com self.value = value.value 69910676Sandreas.hansson@arm.com else: 7009411Sandreas.hansson@arm.com try: 7019411Sandreas.hansson@arm.com # Often addresses are referred to with sizes. Ex: A device 7029411Sandreas.hansson@arm.com # base address is at "512MB". Use toMemorySize() to convert 7033101Sstever@eecs.umich.edu # these into addresses. If the address is not specified with a 7049411Sandreas.hansson@arm.com # "size", an exception will occur and numeric translation will 7059411Sandreas.hansson@arm.com # proceed below. 7069411Sandreas.hansson@arm.com self.value = convert.toMemorySize(value) 7073101Sstever@eecs.umich.edu except (TypeError, ValueError): 7089232Sandreas.hansson@arm.com # Convert number to string and use long() to do automatic 7093101Sstever@eecs.umich.edu # base conversion (requires base=0 for auto-conversion) 7109232Sandreas.hansson@arm.com self.value = long(str(value), base=0) 7113101Sstever@eecs.umich.edu 7123101Sstever@eecs.umich.edu self._check() 7133101Sstever@eecs.umich.edu def __add__(self, other): 7149411Sandreas.hansson@arm.com if isinstance(other, Addr): 7159411Sandreas.hansson@arm.com return self.value + other.value 7169411Sandreas.hansson@arm.com else: 71710676Sandreas.hansson@arm.com return self.value + other 71810676Sandreas.hansson@arm.com def pretty_print(self, value): 7199411Sandreas.hansson@arm.com try: 7209411Sandreas.hansson@arm.com val = convert.toMemorySize(value) 7219411Sandreas.hansson@arm.com except TypeError: 7229411Sandreas.hansson@arm.com val = long(value) 7239411Sandreas.hansson@arm.com return "0x%x" % long(val) 7243101Sstever@eecs.umich.edu 7259232Sandreas.hansson@arm.comclass AddrRange(ParamValue): 7263101Sstever@eecs.umich.edu cxx_type = 'AddrRange' 7273101Sstever@eecs.umich.edu 7283101Sstever@eecs.umich.edu def __init__(self, *args, **kwargs): 7293101Sstever@eecs.umich.edu # Disable interleaving and hashing by default 7309232Sandreas.hansson@arm.com self.intlvHighBit = 0 7313101Sstever@eecs.umich.edu self.xorHighBit = 0 7325219Ssaidi@eecs.umich.edu self.intlvBits = 0 7339232Sandreas.hansson@arm.com self.intlvMatch = 0 7349232Sandreas.hansson@arm.com 7353101Sstever@eecs.umich.edu def handle_kwargs(self, kwargs): 7369232Sandreas.hansson@arm.com # An address range needs to have an upper limit, specified 7379232Sandreas.hansson@arm.com # either explicitly with an end, or as an offset using the 7383101Sstever@eecs.umich.edu # size keyword. 7393101Sstever@eecs.umich.edu if 'end' in kwargs: 7409232Sandreas.hansson@arm.com self.end = Addr(kwargs.pop('end')) 7419232Sandreas.hansson@arm.com elif 'size' in kwargs: 7423101Sstever@eecs.umich.edu 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 7469232Sandreas.hansson@arm.com # Now on to the optional bit 7473101Sstever@eecs.umich.edu if 'intlvHighBit' in kwargs: 7483101Sstever@eecs.umich.edu self.intlvHighBit = int(kwargs.pop('intlvHighBit')) 74911620SMatthew.Poremba@amd.com if 'xorHighBit' in kwargs: 75011620SMatthew.Poremba@amd.com self.xorHighBit = int(kwargs.pop('xorHighBit')) 75111620SMatthew.Poremba@amd.com if 'intlvBits' in kwargs: 7529232Sandreas.hansson@arm.com self.intlvBits = int(kwargs.pop('intlvBits')) 7539232Sandreas.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: 7577673Snate@binkert.org self.start = Addr(kwargs.pop('start')) 7587673Snate@binkert.org handle_kwargs(self, kwargs) 7599232Sandreas.hansson@arm.com 7609235Sandreas.hansson@arm.com elif len(args) == 1: 7617675Snate@binkert.org if kwargs: 7627675Snate@binkert.org self.start = Addr(args[0]) 76311988Sandreas.sandberg@arm.com handle_kwargs(self, kwargs) 76411988Sandreas.sandberg@arm.com elif isinstance(args[0], (list, tuple)): 76511988Sandreas.sandberg@arm.com self.start = Addr(args[0][0]) 76611988Sandreas.sandberg@arm.com self.end = Addr(args[0][1]) 76711988Sandreas.sandberg@arm.com else: 76810458Sandreas.hansson@arm.com self.start = Addr(0) 76910458Sandreas.hansson@arm.com self.end = Addr(args[0]) - 1 77010458Sandreas.hansson@arm.com 77110458Sandreas.hansson@arm.com elif len(args) == 2: 77210458Sandreas.hansson@arm.com self.start = Addr(args[0]) 77311620SMatthew.Poremba@amd.com self.end = Addr(args[1]) 77411620SMatthew.Poremba@amd.com else: 77510458Sandreas.hansson@arm.com raise TypeError, "Too many arguments specified" 77610458Sandreas.hansson@arm.com 77710458Sandreas.hansson@arm.com if kwargs: 77810458Sandreas.hansson@arm.com raise TypeError, "Too many keywords: %s" % kwargs.keys() 77910458Sandreas.hansson@arm.com 78011620SMatthew.Poremba@amd.com def __str__(self): 78111620SMatthew.Poremba@amd.com return '%s:%s' % (self.start, self.end) 78211620SMatthew.Poremba@amd.com 78311620SMatthew.Poremba@amd.com def size(self): 78411620SMatthew.Poremba@amd.com # Divide the size by the size of the interleaving slice 78511620SMatthew.Poremba@amd.com return (long(self.end) - long(self.start) + 1) >> self.intlvBits 78611620SMatthew.Poremba@amd.com 78711620SMatthew.Poremba@amd.com @classmethod 78811620SMatthew.Poremba@amd.com def cxx_predecls(cls, code): 78911620SMatthew.Poremba@amd.com Addr.cxx_predecls(code) 79010458Sandreas.hansson@arm.com code('#include "base/addr_range.hh"') 79110458Sandreas.hansson@arm.com 79210458Sandreas.hansson@arm.com @classmethod 79311620SMatthew.Poremba@amd.com def swig_predecls(cls, code): 79411620SMatthew.Poremba@amd.com Addr.swig_predecls(code) 79510458Sandreas.hansson@arm.com 79610458Sandreas.hansson@arm.com @classmethod 7974762Snate@binkert.org def cxx_ini_predecls(cls, code): 79811991Sandreas.sandberg@arm.com code('#include <sstream>') 79911802Sandreas.sandberg@arm.com 8004762Snate@binkert.org @classmethod 8019411Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 80210676Sandreas.hansson@arm.com code('uint64_t _start, _end;') 80310676Sandreas.hansson@arm.com code('char _sep;') 8043101Sstever@eecs.umich.edu code('std::istringstream _stream(${src});') 8053101Sstever@eecs.umich.edu code('_stream >> _start;') 8063101Sstever@eecs.umich.edu code('_stream.get(_sep);') 8073101Sstever@eecs.umich.edu code('_stream >> _end;') 8083101Sstever@eecs.umich.edu code('bool _ret = !_stream.fail() &&' 8093101Sstever@eecs.umich.edu '_stream.eof() && _sep == \':\';') 81010267SGeoffrey.Blake@arm.com code('if (_ret)') 81110267SGeoffrey.Blake@arm.com code(' ${dest} = AddrRange(_start, _end);') 8123101Sstever@eecs.umich.edu code('${ret} _ret;') 8133101Sstever@eecs.umich.edu 8143102Sstever@eecs.umich.edu def getValue(self): 8153101Sstever@eecs.umich.edu # Go from the Python class to the wrapped C++ class generated 8163101Sstever@eecs.umich.edu # by swig 8173101Sstever@eecs.umich.edu from m5.internal.range import AddrRange 81810267SGeoffrey.Blake@arm.com 81910267SGeoffrey.Blake@arm.com return AddrRange(long(self.start), long(self.end), 82010267SGeoffrey.Blake@arm.com int(self.intlvHighBit), int(self.xorHighBit), 82110267SGeoffrey.Blake@arm.com int(self.intlvBits), int(self.intlvMatch)) 8224762Snate@binkert.org 8234762Snate@binkert.org# Boolean parameter type. Python doesn't let you subclass bool, since 8244762Snate@binkert.org# it doesn't want to let you create multiple instances of True and 8253101Sstever@eecs.umich.edu# False. Thus this is a little more complicated than String. 8263101Sstever@eecs.umich.educlass Bool(ParamValue): 8273101Sstever@eecs.umich.edu cxx_type = 'bool' 8288934SBrad.Beckmann@amd.com cmd_line_settable = True 8298934SBrad.Beckmann@amd.com 8308934SBrad.Beckmann@amd.com def __init__(self, value): 8318934SBrad.Beckmann@amd.com try: 8328934SBrad.Beckmann@amd.com self.value = convert.toBool(value) 8333101Sstever@eecs.umich.edu except TypeError: 8343101Sstever@eecs.umich.edu self.value = bool(value) 8353101Sstever@eecs.umich.edu 8363101Sstever@eecs.umich.edu def __call__(self, value): 8373101Sstever@eecs.umich.edu self.__init__(value) 83810380SAndrew.Bardsley@arm.com return value 83910380SAndrew.Bardsley@arm.com 84010380SAndrew.Bardsley@arm.com def getValue(self): 84110458Sandreas.hansson@arm.com return bool(self.value) 84210458Sandreas.hansson@arm.com 84310458Sandreas.hansson@arm.com def __str__(self): 84410458Sandreas.hansson@arm.com return str(self.value) 84510458Sandreas.hansson@arm.com 84610458Sandreas.hansson@arm.com # implement truth value testing for Bool parameters so that these params 84710458Sandreas.hansson@arm.com # evaluate correctly during the python configuration phase 84810458Sandreas.hansson@arm.com def __nonzero__(self): 84910458Sandreas.hansson@arm.com return bool(self.value) 85010458Sandreas.hansson@arm.com 8513101Sstever@eecs.umich.edu def ini_str(self): 8523101Sstever@eecs.umich.edu if self.value: 8533101Sstever@eecs.umich.edu return 'true' 8543101Sstever@eecs.umich.edu return 'false' 8553101Sstever@eecs.umich.edu 8563101Sstever@eecs.umich.edu def config_value(self): 8573101Sstever@eecs.umich.edu return self.value 8583101Sstever@eecs.umich.edu 8593101Sstever@eecs.umich.edu @classmethod 8603101Sstever@eecs.umich.edu def cxx_ini_predecls(cls, code): 8613101Sstever@eecs.umich.edu # Assume that base/str.hh will be included anyway 8623101Sstever@eecs.umich.edu # code('#include "base/str.hh"') 8634380Sbinkertn@umich.edu pass 8644380Sbinkertn@umich.edu 8654380Sbinkertn@umich.edu @classmethod 8663101Sstever@eecs.umich.edu def cxx_ini_parse(cls, code, src, dest, ret): 8674380Sbinkertn@umich.edu code('%s to_bool(%s, %s);' % (ret, src, dest)) 8684380Sbinkertn@umich.edu 8694380Sbinkertn@umich.edudef IncEthernetAddr(addr, val = 1): 8703101Sstever@eecs.umich.edu bytes = map(lambda x: int(x, 16), addr.split(':')) 8713101Sstever@eecs.umich.edu bytes[5] += val 8723101Sstever@eecs.umich.edu for i in (5, 4, 3, 2, 1): 87310267SGeoffrey.Blake@arm.com val,rem = divmod(bytes[i], 256) 87410267SGeoffrey.Blake@arm.com bytes[i] = rem 8757673Snate@binkert.org if val == 0: 8767673Snate@binkert.org break 8777673Snate@binkert.org bytes[i - 1] += val 8787673Snate@binkert.org assert(bytes[0] <= 255) 8797673Snate@binkert.org return ':'.join(map(lambda x: '%02x' % x, bytes)) 8803101Sstever@eecs.umich.edu 8813101Sstever@eecs.umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 8823101Sstever@eecs.umich.edudef NextEthernetAddr(): 8833101Sstever@eecs.umich.edu global _NextEthernetAddr 8843101Sstever@eecs.umich.edu 8853101Sstever@eecs.umich.edu value = _NextEthernetAddr 8863101Sstever@eecs.umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 8873101Sstever@eecs.umich.edu return value 8883101Sstever@eecs.umich.edu 8893101Sstever@eecs.umich.educlass EthernetAddr(ParamValue): 8903101Sstever@eecs.umich.edu cxx_type = 'Net::EthAddr' 8913101Sstever@eecs.umich.edu ex_str = "00:90:00:00:00:01" 8923101Sstever@eecs.umich.edu cmd_line_settable = True 8939941SGeoffrey.Blake@arm.com 8943101Sstever@eecs.umich.edu @classmethod 8953101Sstever@eecs.umich.edu def cxx_predecls(cls, code): 8963101Sstever@eecs.umich.edu code('#include "base/inet.hh"') 8973101Sstever@eecs.umich.edu 89810267SGeoffrey.Blake@arm.com @classmethod 89910267SGeoffrey.Blake@arm.com def swig_predecls(cls, code): 90010267SGeoffrey.Blake@arm.com code('%include "python/swig/inet.i"') 90110267SGeoffrey.Blake@arm.com 9023101Sstever@eecs.umich.edu def __init__(self, value): 9033101Sstever@eecs.umich.edu if value == NextEthernetAddr: 9044380Sbinkertn@umich.edu self.value = value 9053101Sstever@eecs.umich.edu return 9063101Sstever@eecs.umich.edu 9074762Snate@binkert.org if not isinstance(value, str): 90811988Sandreas.sandberg@arm.com raise TypeError, "expected an ethernet address and didn't get one" 9094762Snate@binkert.org 9104762Snate@binkert.org bytes = value.split(':') 91111228SAndrew.Bardsley@arm.com if len(bytes) != 6: 91211228SAndrew.Bardsley@arm.com raise TypeError, 'invalid ethernet address %s' % value 91311228SAndrew.Bardsley@arm.com 9144380Sbinkertn@umich.edu for byte in bytes: 9154380Sbinkertn@umich.edu if not 0 <= int(byte, base=16) <= 0xff: 9163101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 91710458Sandreas.hansson@arm.com 91810458Sandreas.hansson@arm.com self.value = value 91910458Sandreas.hansson@arm.com 92010458Sandreas.hansson@arm.com def __call__(self, value): 92110458Sandreas.hansson@arm.com self.__init__(value) 9227777Sgblack@eecs.umich.edu return value 9237777Sgblack@eecs.umich.edu 9247777Sgblack@eecs.umich.edu def unproxy(self, base): 9257777Sgblack@eecs.umich.edu if self.value == NextEthernetAddr: 92610267SGeoffrey.Blake@arm.com return EthernetAddr(self.value()) 92710267SGeoffrey.Blake@arm.com return self 9287777Sgblack@eecs.umich.edu 9297777Sgblack@eecs.umich.edu def getValue(self): 9307777Sgblack@eecs.umich.edu from m5.internal.params import EthAddr 9317777Sgblack@eecs.umich.edu return EthAddr(self.value) 9327777Sgblack@eecs.umich.edu 9337777Sgblack@eecs.umich.edu def ini_str(self): 9347777Sgblack@eecs.umich.edu return self.value 9357777Sgblack@eecs.umich.edu 9367777Sgblack@eecs.umich.edu @classmethod 9377777Sgblack@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 9387777Sgblack@eecs.umich.edu code('%s = Net::EthAddr(%s);' % (dest, src)) 9397777Sgblack@eecs.umich.edu code('%s true;' % ret) 9407777Sgblack@eecs.umich.edu 9417777Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of 9427777Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP. 94310267SGeoffrey.Blake@arm.comclass IpAddress(ParamValue): 94410267SGeoffrey.Blake@arm.com cxx_type = 'Net::IpAddress' 94510267SGeoffrey.Blake@arm.com ex_str = "127.0.0.1" 94610267SGeoffrey.Blake@arm.com cmd_line_settable = True 9478579Ssteve.reinhardt@amd.com 9488579Ssteve.reinhardt@amd.com @classmethod 9498579Ssteve.reinhardt@amd.com def cxx_predecls(cls, code): 9508579Ssteve.reinhardt@amd.com code('#include "base/inet.hh"') 9518579Ssteve.reinhardt@amd.com 9528579Ssteve.reinhardt@amd.com @classmethod 9538579Ssteve.reinhardt@amd.com def swig_predecls(cls, code): 9548579Ssteve.reinhardt@amd.com code('%include "python/swig/inet.i"') 9558579Ssteve.reinhardt@amd.com 9568579Ssteve.reinhardt@amd.com def __init__(self, value): 9578579Ssteve.reinhardt@amd.com if isinstance(value, IpAddress): 9588579Ssteve.reinhardt@amd.com self.ip = value.ip 9598579Ssteve.reinhardt@amd.com else: 9608579Ssteve.reinhardt@amd.com try: 9618579Ssteve.reinhardt@amd.com self.ip = convert.toIpAddress(value) 9628579Ssteve.reinhardt@amd.com except TypeError: 9638579Ssteve.reinhardt@amd.com self.ip = long(value) 9648579Ssteve.reinhardt@amd.com self.verifyIp() 9657777Sgblack@eecs.umich.edu 9667777Sgblack@eecs.umich.edu def __call__(self, value): 9677798Sgblack@eecs.umich.edu self.__init__(value) 9687777Sgblack@eecs.umich.edu return value 9697777Sgblack@eecs.umich.edu 97011988Sandreas.sandberg@arm.com def __str__(self): 9717777Sgblack@eecs.umich.edu tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)] 9727777Sgblack@eecs.umich.edu return '%d.%d.%d.%d' % tuple(tup) 9737777Sgblack@eecs.umich.edu 9747777Sgblack@eecs.umich.edu def __eq__(self, other): 9757777Sgblack@eecs.umich.edu if isinstance(other, IpAddress): 9767777Sgblack@eecs.umich.edu return self.ip == other.ip 9777777Sgblack@eecs.umich.edu elif isinstance(other, str): 97810267SGeoffrey.Blake@arm.com try: 97910267SGeoffrey.Blake@arm.com return self.ip == convert.toIpAddress(other) 9807777Sgblack@eecs.umich.edu except: 9817777Sgblack@eecs.umich.edu return False 9827777Sgblack@eecs.umich.edu else: 9837777Sgblack@eecs.umich.edu return self.ip == other 9847777Sgblack@eecs.umich.edu 9857777Sgblack@eecs.umich.edu def __ne__(self, other): 9867777Sgblack@eecs.umich.edu return not (self == other) 9877777Sgblack@eecs.umich.edu 9887777Sgblack@eecs.umich.edu def verifyIp(self): 9897777Sgblack@eecs.umich.edu if self.ip < 0 or self.ip >= (1 << 32): 9907777Sgblack@eecs.umich.edu raise TypeError, "invalid ip address %#08x" % self.ip 9917777Sgblack@eecs.umich.edu 9927777Sgblack@eecs.umich.edu def getValue(self): 9937777Sgblack@eecs.umich.edu from m5.internal.params import IpAddress 9947777Sgblack@eecs.umich.edu return IpAddress(self.ip) 9957777Sgblack@eecs.umich.edu 9967777Sgblack@eecs.umich.edu# When initializing an IpNetmask, pass in an existing IpNetmask, a string of 9977777Sgblack@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 9987777Sgblack@eecs.umich.edu# positional or keyword arguments. 9997777Sgblack@eecs.umich.educlass IpNetmask(IpAddress): 10007777Sgblack@eecs.umich.edu cxx_type = 'Net::IpNetmask' 10017777Sgblack@eecs.umich.edu ex_str = "127.0.0.0/24" 10027777Sgblack@eecs.umich.edu cmd_line_settable = True 10037777Sgblack@eecs.umich.edu 10047777Sgblack@eecs.umich.edu @classmethod 10057777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 10067777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 10077777Sgblack@eecs.umich.edu 10087777Sgblack@eecs.umich.edu @classmethod 10097777Sgblack@eecs.umich.edu def swig_predecls(cls, code): 10107777Sgblack@eecs.umich.edu code('%include "python/swig/inet.i"') 10117777Sgblack@eecs.umich.edu 10127777Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 10137777Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 10147777Sgblack@eecs.umich.edu if key in kwargs: 10157777Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 10167777Sgblack@eecs.umich.edu elif elseVal: 10177777Sgblack@eecs.umich.edu setattr(self, key, elseVal) 10187777Sgblack@eecs.umich.edu else: 10197777Sgblack@eecs.umich.edu raise TypeError, "No value set for %s" % key 10207777Sgblack@eecs.umich.edu 102110267SGeoffrey.Blake@arm.com if len(args) == 0: 102210267SGeoffrey.Blake@arm.com handle_kwarg(self, kwargs, 'ip') 102310267SGeoffrey.Blake@arm.com handle_kwarg(self, kwargs, 'netmask') 102410267SGeoffrey.Blake@arm.com 10258579Ssteve.reinhardt@amd.com elif len(args) == 1: 10268579Ssteve.reinhardt@amd.com if kwargs: 10278579Ssteve.reinhardt@amd.com if not 'ip' in kwargs and not 'netmask' in kwargs: 10288579Ssteve.reinhardt@amd.com raise TypeError, "Invalid arguments" 10298579Ssteve.reinhardt@amd.com handle_kwarg(self, kwargs, 'ip', args[0]) 10308579Ssteve.reinhardt@amd.com handle_kwarg(self, kwargs, 'netmask', args[0]) 10318579Ssteve.reinhardt@amd.com elif isinstance(args[0], IpNetmask): 10328579Ssteve.reinhardt@amd.com self.ip = args[0].ip 10338579Ssteve.reinhardt@amd.com self.netmask = args[0].netmask 10348579Ssteve.reinhardt@amd.com else: 10358579Ssteve.reinhardt@amd.com (self.ip, self.netmask) = convert.toIpNetmask(args[0]) 10368579Ssteve.reinhardt@amd.com 10378579Ssteve.reinhardt@amd.com elif len(args) == 2: 10388579Ssteve.reinhardt@amd.com self.ip = args[0] 10397777Sgblack@eecs.umich.edu self.netmask = args[1] 10407777Sgblack@eecs.umich.edu else: 10417777Sgblack@eecs.umich.edu raise TypeError, "Too many arguments specified" 10427777Sgblack@eecs.umich.edu 10437777Sgblack@eecs.umich.edu if kwargs: 10447777Sgblack@eecs.umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 104511988Sandreas.sandberg@arm.com 10467777Sgblack@eecs.umich.edu self.verify() 10477777Sgblack@eecs.umich.edu 10487777Sgblack@eecs.umich.edu def __call__(self, value): 10497777Sgblack@eecs.umich.edu self.__init__(value) 10507777Sgblack@eecs.umich.edu return value 10517777Sgblack@eecs.umich.edu 105210267SGeoffrey.Blake@arm.com def __str__(self): 105310267SGeoffrey.Blake@arm.com return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask) 10547777Sgblack@eecs.umich.edu 10557777Sgblack@eecs.umich.edu def __eq__(self, other): 10567777Sgblack@eecs.umich.edu if isinstance(other, IpNetmask): 10577777Sgblack@eecs.umich.edu return self.ip == other.ip and self.netmask == other.netmask 10587777Sgblack@eecs.umich.edu elif isinstance(other, str): 10597777Sgblack@eecs.umich.edu try: 10607777Sgblack@eecs.umich.edu return (self.ip, self.netmask) == convert.toIpNetmask(other) 10617777Sgblack@eecs.umich.edu except: 10627777Sgblack@eecs.umich.edu return False 10637777Sgblack@eecs.umich.edu else: 10647777Sgblack@eecs.umich.edu return False 10657777Sgblack@eecs.umich.edu 10667777Sgblack@eecs.umich.edu def verify(self): 10677777Sgblack@eecs.umich.edu self.verifyIp() 10687777Sgblack@eecs.umich.edu if self.netmask < 0 or self.netmask > 32: 10697777Sgblack@eecs.umich.edu raise TypeError, "invalid netmask %d" % netmask 10707777Sgblack@eecs.umich.edu 10717777Sgblack@eecs.umich.edu def getValue(self): 10727777Sgblack@eecs.umich.edu from m5.internal.params import IpNetmask 10737777Sgblack@eecs.umich.edu return IpNetmask(self.ip, self.netmask) 10747777Sgblack@eecs.umich.edu 10757777Sgblack@eecs.umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of 10767777Sgblack@eecs.umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments. 10777777Sgblack@eecs.umich.educlass IpWithPort(IpAddress): 10787777Sgblack@eecs.umich.edu cxx_type = 'Net::IpWithPort' 10797777Sgblack@eecs.umich.edu ex_str = "127.0.0.1:80" 10807777Sgblack@eecs.umich.edu cmd_line_settable = True 10817777Sgblack@eecs.umich.edu 10827777Sgblack@eecs.umich.edu @classmethod 10837777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 10847777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 10857777Sgblack@eecs.umich.edu 10867777Sgblack@eecs.umich.edu @classmethod 10877777Sgblack@eecs.umich.edu def swig_predecls(cls, code): 10887777Sgblack@eecs.umich.edu code('%include "python/swig/inet.i"') 10897777Sgblack@eecs.umich.edu 10907777Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 10917777Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 10927777Sgblack@eecs.umich.edu if key in kwargs: 10937777Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 10947777Sgblack@eecs.umich.edu elif elseVal: 109510267SGeoffrey.Blake@arm.com setattr(self, key, elseVal) 109610267SGeoffrey.Blake@arm.com else: 109710267SGeoffrey.Blake@arm.com raise TypeError, "No value set for %s" % key 109810267SGeoffrey.Blake@arm.com 10998579Ssteve.reinhardt@amd.com if len(args) == 0: 11008579Ssteve.reinhardt@amd.com handle_kwarg(self, kwargs, 'ip') 11018579Ssteve.reinhardt@amd.com handle_kwarg(self, kwargs, 'port') 11028579Ssteve.reinhardt@amd.com 11038579Ssteve.reinhardt@amd.com elif len(args) == 1: 11048579Ssteve.reinhardt@amd.com if kwargs: 11058579Ssteve.reinhardt@amd.com if not 'ip' in kwargs and not 'port' in kwargs: 11068579Ssteve.reinhardt@amd.com raise TypeError, "Invalid arguments" 11078579Ssteve.reinhardt@amd.com handle_kwarg(self, kwargs, 'ip', args[0]) 11088579Ssteve.reinhardt@amd.com handle_kwarg(self, kwargs, 'port', args[0]) 11098579Ssteve.reinhardt@amd.com elif isinstance(args[0], IpWithPort): 11108579Ssteve.reinhardt@amd.com self.ip = args[0].ip 11118579Ssteve.reinhardt@amd.com self.port = args[0].port 11128579Ssteve.reinhardt@amd.com else: 11137777Sgblack@eecs.umich.edu (self.ip, self.port) = convert.toIpWithPort(args[0]) 11147777Sgblack@eecs.umich.edu 11157777Sgblack@eecs.umich.edu elif len(args) == 2: 11167777Sgblack@eecs.umich.edu self.ip = args[0] 11177777Sgblack@eecs.umich.edu self.port = args[1] 11187777Sgblack@eecs.umich.edu else: 111911988Sandreas.sandberg@arm.com raise TypeError, "Too many arguments specified" 11207777Sgblack@eecs.umich.edu 11217777Sgblack@eecs.umich.edu if kwargs: 11223932Sbinkertn@umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 112310380SAndrew.Bardsley@arm.com 11243932Sbinkertn@umich.edu self.verify() 11253932Sbinkertn@umich.edu 11263932Sbinkertn@umich.edu def __call__(self, value): 11273932Sbinkertn@umich.edu self.__init__(value) 11283932Sbinkertn@umich.edu return value 11293932Sbinkertn@umich.edu 11303932Sbinkertn@umich.edu def __str__(self): 11313932Sbinkertn@umich.edu return "%s:%d" % (super(IpWithPort, self).__str__(), self.port) 11323932Sbinkertn@umich.edu 11333932Sbinkertn@umich.edu def __eq__(self, other): 11343932Sbinkertn@umich.edu if isinstance(other, IpWithPort): 11353885Sbinkertn@umich.edu return self.ip == other.ip and self.port == other.port 11363932Sbinkertn@umich.edu elif isinstance(other, str): 11373932Sbinkertn@umich.edu try: 11383885Sbinkertn@umich.edu return (self.ip, self.port) == convert.toIpWithPort(other) 11393932Sbinkertn@umich.edu except: 11403932Sbinkertn@umich.edu return False 11413932Sbinkertn@umich.edu else: 11423932Sbinkertn@umich.edu return False 11433932Sbinkertn@umich.edu 11443932Sbinkertn@umich.edu def verify(self): 11453932Sbinkertn@umich.edu self.verifyIp() 11463932Sbinkertn@umich.edu if self.port < 0 or self.port > 0xffff: 11473932Sbinkertn@umich.edu raise TypeError, "invalid port %d" % self.port 11483932Sbinkertn@umich.edu 11493932Sbinkertn@umich.edu def getValue(self): 11503932Sbinkertn@umich.edu from m5.internal.params import IpWithPort 11513932Sbinkertn@umich.edu return IpWithPort(self.ip, self.port) 11523932Sbinkertn@umich.edu 11533932Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 11543932Sbinkertn@umich.edu "%a %b %d %H:%M:%S %Y", 11553932Sbinkertn@umich.edu "%Y/%m/%d %H:%M:%S", 11563932Sbinkertn@umich.edu "%Y/%m/%d %H:%M", 11573885Sbinkertn@umich.edu "%Y/%m/%d", 11583885Sbinkertn@umich.edu "%m/%d/%Y %H:%M:%S", 11593885Sbinkertn@umich.edu "%m/%d/%Y %H:%M", 11603885Sbinkertn@umich.edu "%m/%d/%Y", 11614762Snate@binkert.org "%m/%d/%y %H:%M:%S", 11627673Snate@binkert.org "%m/%d/%y %H:%M", 11637673Snate@binkert.org "%m/%d/%y"] 11647673Snate@binkert.org 11657673Snate@binkert.org 11667673Snate@binkert.orgdef parse_time(value): 11673885Sbinkertn@umich.edu from time import gmtime, strptime, struct_time, time 11683932Sbinkertn@umich.edu from datetime import datetime, date 11693885Sbinkertn@umich.edu 117010267SGeoffrey.Blake@arm.com if isinstance(value, struct_time): 117110267SGeoffrey.Blake@arm.com return value 117210267SGeoffrey.Blake@arm.com 117310267SGeoffrey.Blake@arm.com if isinstance(value, (int, long)): 11744762Snate@binkert.org return gmtime(value) 117511988Sandreas.sandberg@arm.com 117611988Sandreas.sandberg@arm.com if isinstance(value, (datetime, date)): 11774762Snate@binkert.org return value.timetuple() 117811988Sandreas.sandberg@arm.com 11794762Snate@binkert.org if isinstance(value, str): 11803885Sbinkertn@umich.edu if value in ('Now', 'Today'): 11814762Snate@binkert.org return time.gmtime(time.time()) 11823885Sbinkertn@umich.edu 11833885Sbinkertn@umich.edu for format in time_formats: 11843932Sbinkertn@umich.edu try: 11853885Sbinkertn@umich.edu return strptime(value, format) 11868664SAli.Saidi@ARM.com except ValueError: 118710380SAndrew.Bardsley@arm.com pass 11888664SAli.Saidi@ARM.com 11898664SAli.Saidi@ARM.com raise ValueError, "Could not parse '%s' as a time" % value 119010458Sandreas.hansson@arm.com 119110458Sandreas.hansson@arm.comclass Time(ParamValue): 119210458Sandreas.hansson@arm.com cxx_type = 'tm' 119310458Sandreas.hansson@arm.com 119410458Sandreas.hansson@arm.com @classmethod 119510458Sandreas.hansson@arm.com def cxx_predecls(cls, code): 119610458Sandreas.hansson@arm.com code('#include <time.h>') 119710458Sandreas.hansson@arm.com 119810458Sandreas.hansson@arm.com @classmethod 119910458Sandreas.hansson@arm.com def swig_predecls(cls, code): 12003101Sstever@eecs.umich.edu code('%include "python/swig/time.i"') 12013101Sstever@eecs.umich.edu 12023101Sstever@eecs.umich.edu def __init__(self, value): 12033101Sstever@eecs.umich.edu self.value = parse_time(value) 12043101Sstever@eecs.umich.edu 12053101Sstever@eecs.umich.edu def __call__(self, value): 12063101Sstever@eecs.umich.edu self.__init__(value) 12073101Sstever@eecs.umich.edu return value 12083101Sstever@eecs.umich.edu 12093101Sstever@eecs.umich.edu def getValue(self): 12103101Sstever@eecs.umich.edu from m5.internal.params import tm 12113101Sstever@eecs.umich.edu 12123101Sstever@eecs.umich.edu c_time = tm() 12133101Sstever@eecs.umich.edu py_time = self.value 12144762Snate@binkert.org 12153101Sstever@eecs.umich.edu # UNIX is years since 1900 12165033Smilesck@eecs.umich.edu c_time.tm_year = py_time.tm_year - 1900; 12174762Snate@binkert.org 12184762Snate@binkert.org # Python starts at 1, UNIX starts at 0 12194762Snate@binkert.org c_time.tm_mon = py_time.tm_mon - 1; 12204762Snate@binkert.org c_time.tm_mday = py_time.tm_mday; 12214762Snate@binkert.org c_time.tm_hour = py_time.tm_hour; 12224762Snate@binkert.org c_time.tm_min = py_time.tm_min; 12234762Snate@binkert.org c_time.tm_sec = py_time.tm_sec; 12243101Sstever@eecs.umich.edu 12253101Sstever@eecs.umich.edu # Python has 0 as Monday, UNIX is 0 as sunday 12263101Sstever@eecs.umich.edu c_time.tm_wday = py_time.tm_wday + 1 12273101Sstever@eecs.umich.edu if c_time.tm_wday > 6: 12283101Sstever@eecs.umich.edu c_time.tm_wday -= 7; 12293101Sstever@eecs.umich.edu 12303101Sstever@eecs.umich.edu # Python starts at 1, Unix starts at 0 12313101Sstever@eecs.umich.edu c_time.tm_yday = py_time.tm_yday - 1; 12323101Sstever@eecs.umich.edu 12333101Sstever@eecs.umich.edu return c_time 12343101Sstever@eecs.umich.edu 12353101Sstever@eecs.umich.edu def __str__(self): 12363101Sstever@eecs.umich.edu return time.asctime(self.value) 12373101Sstever@eecs.umich.edu 12383101Sstever@eecs.umich.edu def ini_str(self): 12393101Sstever@eecs.umich.edu return str(self) 12403101Sstever@eecs.umich.edu 12413101Sstever@eecs.umich.edu def get_config_as_dict(self): 12423101Sstever@eecs.umich.edu assert false 12433101Sstever@eecs.umich.edu return str(self) 12444762Snate@binkert.org 12453101Sstever@eecs.umich.edu @classmethod 12463101Sstever@eecs.umich.edu def cxx_ini_predecls(cls, code): 12473101Sstever@eecs.umich.edu code('#include <time.h>') 12483101Sstever@eecs.umich.edu 12493101Sstever@eecs.umich.edu @classmethod 12503101Sstever@eecs.umich.edu def cxx_ini_parse(cls, code, src, dest, ret): 12517673Snate@binkert.org code('char *_parse_ret = strptime((${src}).c_str(),') 125210201SAndrew.Bardsley@arm.com code(' "%a %b %d %H:%M:%S %Y", &(${dest}));') 125310201SAndrew.Bardsley@arm.com code('${ret} _parse_ret && *_parse_ret == \'\\0\';'); 125410201SAndrew.Bardsley@arm.com 125510201SAndrew.Bardsley@arm.com# Enumerated types are a little more complex. The user specifies the 125610201SAndrew.Bardsley@arm.com# type as Enum(foo) where foo is either a list or dictionary of 12577673Snate@binkert.org# alternatives (typically strings, but not necessarily so). (In the 125810201SAndrew.Bardsley@arm.com# long run, the integer value of the parameter will be the list index 125910201SAndrew.Bardsley@arm.com# or the corresponding dictionary value. For now, since we only check 12607673Snate@binkert.org# that the alternative is valid and then spit it into a .ini file, 126110201SAndrew.Bardsley@arm.com# there's not much point in using the dictionary.) 12627673Snate@binkert.org 12637673Snate@binkert.org# What Enum() must do is generate a new type encapsulating the 12647673Snate@binkert.org# provided list/dictionary so that specific values of the parameter 12654762Snate@binkert.org# can be instances of that type. We define two hidden internal 12667673Snate@binkert.org# classes (_ListEnum and _DictEnum) to serve as base classes, then 12678902Sandreas.hansson@arm.com# derive the new type from the appropriate base class on the fly. 12687673Snate@binkert.org 126910201SAndrew.Bardsley@arm.comallEnums = {} 12704762Snate@binkert.org# Metaclass for Enum types 127110201SAndrew.Bardsley@arm.comclass MetaEnum(MetaParamValue): 127210201SAndrew.Bardsley@arm.com def __new__(mcls, name, bases, dict): 127310201SAndrew.Bardsley@arm.com assert name not in allEnums 127410201SAndrew.Bardsley@arm.com 127510201SAndrew.Bardsley@arm.com cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 127610201SAndrew.Bardsley@arm.com allEnums[name] = cls 127710201SAndrew.Bardsley@arm.com return cls 127810201SAndrew.Bardsley@arm.com 127910201SAndrew.Bardsley@arm.com def __init__(cls, name, bases, init_dict): 12807673Snate@binkert.org if init_dict.has_key('map'): 12817673Snate@binkert.org if not isinstance(cls.map, dict): 128210201SAndrew.Bardsley@arm.com raise TypeError, "Enum-derived class attribute 'map' " \ 128310201SAndrew.Bardsley@arm.com "must be of type dict" 128410201SAndrew.Bardsley@arm.com # build list of value strings from map 128510201SAndrew.Bardsley@arm.com cls.vals = cls.map.keys() 128610201SAndrew.Bardsley@arm.com cls.vals.sort() 128710201SAndrew.Bardsley@arm.com elif init_dict.has_key('vals'): 128810201SAndrew.Bardsley@arm.com if not isinstance(cls.vals, list): 128910201SAndrew.Bardsley@arm.com raise TypeError, "Enum-derived class attribute 'vals' " \ 129010201SAndrew.Bardsley@arm.com "must be of type list" 129110201SAndrew.Bardsley@arm.com # build string->value map from vals sequence 129210201SAndrew.Bardsley@arm.com cls.map = {} 129310201SAndrew.Bardsley@arm.com for idx,val in enumerate(cls.vals): 129410201SAndrew.Bardsley@arm.com cls.map[val] = idx 129510201SAndrew.Bardsley@arm.com else: 129610201SAndrew.Bardsley@arm.com raise TypeError, "Enum-derived class must define "\ 12974762Snate@binkert.org "attribute 'map' or 'vals'" 12987673Snate@binkert.org 129910201SAndrew.Bardsley@arm.com cls.cxx_type = 'Enums::%s' % name 130010201SAndrew.Bardsley@arm.com 130110201SAndrew.Bardsley@arm.com super(MetaEnum, cls).__init__(name, bases, init_dict) 130210201SAndrew.Bardsley@arm.com 130310201SAndrew.Bardsley@arm.com # Generate C++ class declaration for this enum type. 130410201SAndrew.Bardsley@arm.com # Note that we wrap the enum in a class/struct to act as a namespace, 13053101Sstever@eecs.umich.edu # so that the enum strings can be brief w/o worrying about collisions. 130611988Sandreas.sandberg@arm.com def cxx_decl(cls, code): 130711988Sandreas.sandberg@arm.com wrapper_name = cls.wrapper_name 130811988Sandreas.sandberg@arm.com wrapper = 'struct' if cls.wrapper_is_struct else 'namespace' 130911988Sandreas.sandberg@arm.com name = cls.__name__ if cls.enum_name is None else cls.enum_name 131011988Sandreas.sandberg@arm.com idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name) 131111988Sandreas.sandberg@arm.com 131211988Sandreas.sandberg@arm.com code('''\ 131311988Sandreas.sandberg@arm.com#ifndef $idem_macro 131411988Sandreas.sandberg@arm.com#define $idem_macro 131511988Sandreas.sandberg@arm.com 131611988Sandreas.sandberg@arm.com$wrapper $wrapper_name { 131711988Sandreas.sandberg@arm.com enum $name { 131811988Sandreas.sandberg@arm.com''') 131911988Sandreas.sandberg@arm.com code.indent(2) 132011988Sandreas.sandberg@arm.com for val in cls.vals: 132111988Sandreas.sandberg@arm.com code('$val = ${{cls.map[val]}},') 132211988Sandreas.sandberg@arm.com code('Num_$name = ${{len(cls.vals)}}') 132311988Sandreas.sandberg@arm.com code.dedent(2) 132411988Sandreas.sandberg@arm.com code(' };') 132511988Sandreas.sandberg@arm.com 132611988Sandreas.sandberg@arm.com if cls.wrapper_is_struct: 132711988Sandreas.sandberg@arm.com code(' static const char *${name}Strings[Num_${name}];') 132811988Sandreas.sandberg@arm.com code('};') 132911988Sandreas.sandberg@arm.com else: 133011988Sandreas.sandberg@arm.com code('extern const char *${name}Strings[Num_${name}];') 133111988Sandreas.sandberg@arm.com code('}') 133211988Sandreas.sandberg@arm.com 133311988Sandreas.sandberg@arm.com code() 133411988Sandreas.sandberg@arm.com code('#endif // $idem_macro') 133511988Sandreas.sandberg@arm.com 133611988Sandreas.sandberg@arm.com def cxx_def(cls, code): 133711988Sandreas.sandberg@arm.com wrapper_name = cls.wrapper_name 133811988Sandreas.sandberg@arm.com file_name = cls.__name__ 133911988Sandreas.sandberg@arm.com name = cls.__name__ if cls.enum_name is None else cls.enum_name 13408596Ssteve.reinhardt@amd.com 13413101Sstever@eecs.umich.edu code('#include "enums/$file_name.hh"') 13423101Sstever@eecs.umich.edu if cls.wrapper_is_struct: 13433101Sstever@eecs.umich.edu code('const char *${wrapper_name}::${name}Strings' 13443101Sstever@eecs.umich.edu '[Num_${name}] =') 134510267SGeoffrey.Blake@arm.com else: 13463101Sstever@eecs.umich.edu code('namespace Enums {') 134710201SAndrew.Bardsley@arm.com code.indent(1) 134810201SAndrew.Bardsley@arm.com code(' const char *${name}Strings[Num_${name}] =') 134910201SAndrew.Bardsley@arm.com 135010201SAndrew.Bardsley@arm.com code('{') 135110201SAndrew.Bardsley@arm.com code.indent(1) 135210201SAndrew.Bardsley@arm.com for val in cls.vals: 135310201SAndrew.Bardsley@arm.com code('"$val",') 135410201SAndrew.Bardsley@arm.com code.dedent(1) 135510201SAndrew.Bardsley@arm.com code('};') 13563101Sstever@eecs.umich.edu 13573101Sstever@eecs.umich.edu if not cls.wrapper_is_struct: 13583101Sstever@eecs.umich.edu code('} // namespace $wrapper_name') 13593101Sstever@eecs.umich.edu code.dedent(1) 13603101Sstever@eecs.umich.edu 13613101Sstever@eecs.umich.edu def swig_decl(cls, code): 136210267SGeoffrey.Blake@arm.com name = cls.__name__ 136310267SGeoffrey.Blake@arm.com code('''\ 136410267SGeoffrey.Blake@arm.com%module(package="m5.internal") enum_$name 136510267SGeoffrey.Blake@arm.com 13667675Snate@binkert.org%{ 13677675Snate@binkert.org#include "enums/$name.hh" 13687675Snate@binkert.org%} 13697675Snate@binkert.org 13707675Snate@binkert.org%include "enums/$name.hh" 137110458Sandreas.hansson@arm.com''') 137210458Sandreas.hansson@arm.com 137310458Sandreas.hansson@arm.com 137410458Sandreas.hansson@arm.com# Base class for enum types. 137510458Sandreas.hansson@arm.comclass Enum(ParamValue): 137610458Sandreas.hansson@arm.com __metaclass__ = MetaEnum 137710458Sandreas.hansson@arm.com vals = [] 137810458Sandreas.hansson@arm.com cmd_line_settable = True 137910458Sandreas.hansson@arm.com 138010458Sandreas.hansson@arm.com # The name of the wrapping namespace or struct 138110458Sandreas.hansson@arm.com wrapper_name = 'Enums' 138210458Sandreas.hansson@arm.com 13834762Snate@binkert.org # If true, the enum is wrapped in a struct rather than a namespace 138411988Sandreas.sandberg@arm.com wrapper_is_struct = False 138511988Sandreas.sandberg@arm.com 138611988Sandreas.sandberg@arm.com # If not None, use this as the enum name rather than this class name 13874762Snate@binkert.org enum_name = None 13883101Sstever@eecs.umich.edu 13893101Sstever@eecs.umich.edu def __init__(self, value): 13903101Sstever@eecs.umich.edu if value not in self.map: 13913101Sstever@eecs.umich.edu raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 13923101Sstever@eecs.umich.edu % (value, self.vals) 13933101Sstever@eecs.umich.edu self.value = value 13944167Sbinkertn@umich.edu 13953101Sstever@eecs.umich.edu def __call__(self, value): 139610267SGeoffrey.Blake@arm.com self.__init__(value) 139710267SGeoffrey.Blake@arm.com return value 13987673Snate@binkert.org 13997673Snate@binkert.org @classmethod 14007673Snate@binkert.org def cxx_predecls(cls, code): 14017673Snate@binkert.org code('#include "enums/$0.hh"', cls.__name__) 14027673Snate@binkert.org 140310267SGeoffrey.Blake@arm.com @classmethod 140410267SGeoffrey.Blake@arm.com def swig_predecls(cls, code): 140510267SGeoffrey.Blake@arm.com code('%import "python/m5/internal/enum_$0.i"', cls.__name__) 140610267SGeoffrey.Blake@arm.com 14074762Snate@binkert.org @classmethod 14084762Snate@binkert.org def cxx_ini_parse(cls, code, src, dest, ret): 14094762Snate@binkert.org code('if (false) {') 141010458Sandreas.hansson@arm.com for elem_name in cls.map.iterkeys(): 141110458Sandreas.hansson@arm.com code('} else if (%s == "%s") {' % (src, elem_name)) 141210458Sandreas.hansson@arm.com code.indent() 141310458Sandreas.hansson@arm.com code('%s = Enums::%s;' % (dest, elem_name)) 141410458Sandreas.hansson@arm.com code('%s true;' % ret) 141510458Sandreas.hansson@arm.com code.dedent() 141610458Sandreas.hansson@arm.com code('} else {') 141710458Sandreas.hansson@arm.com code(' %s false;' % ret) 141810458Sandreas.hansson@arm.com code('}') 141910458Sandreas.hansson@arm.com 14204167Sbinkertn@umich.edu def getValue(self): 142110267SGeoffrey.Blake@arm.com return int(self.map[self.value]) 142210267SGeoffrey.Blake@arm.com 14233101Sstever@eecs.umich.edu def __str__(self): 14244167Sbinkertn@umich.edu return self.value 14254167Sbinkertn@umich.edu 14264167Sbinkertn@umich.edu# how big does a rounding error need to be before we warn about it? 14274167Sbinkertn@umich.edufrequency_tolerance = 0.001 # 0.1% 14284167Sbinkertn@umich.edu 14294167Sbinkertn@umich.educlass TickParamValue(NumericParamValue): 14304167Sbinkertn@umich.edu cxx_type = 'Tick' 14314167Sbinkertn@umich.edu ex_str = "1MHz" 14324167Sbinkertn@umich.edu cmd_line_settable = True 14334167Sbinkertn@umich.edu 14344167Sbinkertn@umich.edu @classmethod 14354167Sbinkertn@umich.edu def cxx_predecls(cls, code): 14363101Sstever@eecs.umich.edu code('#include "base/types.hh"') 143710267SGeoffrey.Blake@arm.com 143810267SGeoffrey.Blake@arm.com @classmethod 143910267SGeoffrey.Blake@arm.com def swig_predecls(cls, code): 144010267SGeoffrey.Blake@arm.com code('%import "stdint.i"') 14413101Sstever@eecs.umich.edu code('%import "base/types.hh"') 14423101Sstever@eecs.umich.edu 14433101Sstever@eecs.umich.edu def __call__(self, value): 14443101Sstever@eecs.umich.edu self.__init__(value) 14453101Sstever@eecs.umich.edu return value 14463101Sstever@eecs.umich.edu 14473101Sstever@eecs.umich.edu def getValue(self): 14484762Snate@binkert.org return long(self.value) 14494762Snate@binkert.org 14504762Snate@binkert.org @classmethod 14514762Snate@binkert.org def cxx_ini_predecls(cls, code): 14524762Snate@binkert.org code('#include <sstream>') 14534762Snate@binkert.org 14544762Snate@binkert.org # Ticks are expressed in seconds in JSON files and in plain 145510380SAndrew.Bardsley@arm.com # Ticks in .ini files. Switch based on a config flag 145610380SAndrew.Bardsley@arm.com @classmethod 145710380SAndrew.Bardsley@arm.com def cxx_ini_parse(self, code, src, dest, ret): 14583101Sstever@eecs.umich.edu code('${ret} to_number(${src}, ${dest});') 14593101Sstever@eecs.umich.edu 14604762Snate@binkert.orgclass Latency(TickParamValue): 14613101Sstever@eecs.umich.edu ex_str = "100ns" 14624167Sbinkertn@umich.edu 146310267SGeoffrey.Blake@arm.com def __init__(self, value): 146410267SGeoffrey.Blake@arm.com if isinstance(value, (Latency, Clock)): 14653101Sstever@eecs.umich.edu self.ticks = value.ticks 14664167Sbinkertn@umich.edu self.value = value.value 14674167Sbinkertn@umich.edu elif isinstance(value, Frequency): 14684167Sbinkertn@umich.edu self.ticks = value.ticks 14694167Sbinkertn@umich.edu self.value = 1.0 / value.value 14704167Sbinkertn@umich.edu elif value.endswith('t'): 14714167Sbinkertn@umich.edu self.ticks = True 14724167Sbinkertn@umich.edu self.value = int(value[:-1]) 14734167Sbinkertn@umich.edu else: 14744167Sbinkertn@umich.edu self.ticks = False 14754167Sbinkertn@umich.edu self.value = convert.toLatency(value) 14764167Sbinkertn@umich.edu 14774167Sbinkertn@umich.edu def __call__(self, value): 14783101Sstever@eecs.umich.edu self.__init__(value) 147910267SGeoffrey.Blake@arm.com return value 148010267SGeoffrey.Blake@arm.com 148110267SGeoffrey.Blake@arm.com def __getattr__(self, attr): 148210267SGeoffrey.Blake@arm.com if attr in ('latency', 'period'): 14833101Sstever@eecs.umich.edu return self 14843101Sstever@eecs.umich.edu if attr == 'frequency': 14853101Sstever@eecs.umich.edu return Frequency(self) 14863101Sstever@eecs.umich.edu raise AttributeError, "Latency object has no attribute '%s'" % attr 14873101Sstever@eecs.umich.edu 14883101Sstever@eecs.umich.edu def getValue(self): 14893101Sstever@eecs.umich.edu if self.ticks or self.value == 0: 14904167Sbinkertn@umich.edu value = self.value 14914762Snate@binkert.org else: 14924762Snate@binkert.org value = ticks.fromSeconds(self.value) 14934762Snate@binkert.org return long(value) 14944762Snate@binkert.org 14954762Snate@binkert.org def config_value(self): 14964762Snate@binkert.org return self.getValue() 14974762Snate@binkert.org 149810380SAndrew.Bardsley@arm.com # convert latency to ticks 149910380SAndrew.Bardsley@arm.com def ini_str(self): 150010380SAndrew.Bardsley@arm.com return '%d' % self.getValue() 15013101Sstever@eecs.umich.edu 15024762Snate@binkert.orgclass Frequency(TickParamValue): 15033101Sstever@eecs.umich.edu ex_str = "1GHz" 150410019Sandreas.hansson@arm.com 150510019Sandreas.hansson@arm.com def __init__(self, value): 150610019Sandreas.hansson@arm.com if isinstance(value, (Latency, Clock)): 15073101Sstever@eecs.umich.edu if value.value == 0: 15084167Sbinkertn@umich.edu self.value = 0 15094167Sbinkertn@umich.edu else: 15104167Sbinkertn@umich.edu self.value = 1.0 / value.value 15114167Sbinkertn@umich.edu self.ticks = value.ticks 15124167Sbinkertn@umich.edu elif isinstance(value, Frequency): 15134167Sbinkertn@umich.edu self.value = value.value 15144167Sbinkertn@umich.edu self.ticks = value.ticks 15154167Sbinkertn@umich.edu else: 15164167Sbinkertn@umich.edu self.ticks = False 15174167Sbinkertn@umich.edu self.value = convert.toFrequency(value) 15184167Sbinkertn@umich.edu 15194167Sbinkertn@umich.edu def __call__(self, value): 15203101Sstever@eecs.umich.edu self.__init__(value) 152110267SGeoffrey.Blake@arm.com return value 152210267SGeoffrey.Blake@arm.com 152310267SGeoffrey.Blake@arm.com def __getattr__(self, attr): 152410267SGeoffrey.Blake@arm.com if attr == 'frequency': 152510267SGeoffrey.Blake@arm.com return self 152610267SGeoffrey.Blake@arm.com if attr in ('latency', 'period'): 152710267SGeoffrey.Blake@arm.com return Latency(self) 15283101Sstever@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 15293101Sstever@eecs.umich.edu 15303101Sstever@eecs.umich.edu # convert latency to ticks 15313101Sstever@eecs.umich.edu def getValue(self): 15323101Sstever@eecs.umich.edu if self.ticks or self.value == 0: 15333101Sstever@eecs.umich.edu value = self.value 15343101Sstever@eecs.umich.edu else: 15354762Snate@binkert.org value = ticks.fromSeconds(1.0 / self.value) 15364762Snate@binkert.org return long(value) 15374762Snate@binkert.org 153810380SAndrew.Bardsley@arm.com def config_value(self): 153910380SAndrew.Bardsley@arm.com return self.getValue() 154010380SAndrew.Bardsley@arm.com 15413101Sstever@eecs.umich.edu def ini_str(self): 15423101Sstever@eecs.umich.edu return '%d' % self.getValue() 15433101Sstever@eecs.umich.edu 15449827Sakash.bagdia@arm.com# A generic Frequency and/or Latency value. Value is stored as a 15459827Sakash.bagdia@arm.com# latency, just like Latency and Frequency. 154610267SGeoffrey.Blake@arm.comclass Clock(TickParamValue): 154711498Sakash.bagdia@ARM.com def __init__(self, value): 154810267SGeoffrey.Blake@arm.com if isinstance(value, (Latency, Clock)): 15499827Sakash.bagdia@arm.com self.ticks = value.ticks 15509827Sakash.bagdia@arm.com self.value = value.value 15519827Sakash.bagdia@arm.com elif isinstance(value, Frequency): 15529827Sakash.bagdia@arm.com self.ticks = value.ticks 15539827Sakash.bagdia@arm.com self.value = 1.0 / value.value 155410267SGeoffrey.Blake@arm.com elif value.endswith('t'): 155510267SGeoffrey.Blake@arm.com self.ticks = True 155610267SGeoffrey.Blake@arm.com self.value = int(value[:-1]) 155710267SGeoffrey.Blake@arm.com else: 155810267SGeoffrey.Blake@arm.com self.ticks = False 15599827Sakash.bagdia@arm.com self.value = convert.anyToLatency(value) 156010267SGeoffrey.Blake@arm.com 15619827Sakash.bagdia@arm.com def __call__(self, value): 15629827Sakash.bagdia@arm.com self.__init__(value) 15639827Sakash.bagdia@arm.com return value 15649827Sakash.bagdia@arm.com 15659827Sakash.bagdia@arm.com def __str__(self): 15669827Sakash.bagdia@arm.com return "%s" % Latency(self) 15679827Sakash.bagdia@arm.com 15689827Sakash.bagdia@arm.com def __getattr__(self, attr): 156910458Sandreas.hansson@arm.com if attr == 'frequency': 157010458Sandreas.hansson@arm.com return Frequency(self) 157110458Sandreas.hansson@arm.com if attr in ('latency', 'period'): 157210458Sandreas.hansson@arm.com return Latency(self) 157310458Sandreas.hansson@arm.com raise AttributeError, "Frequency object has no attribute '%s'" % attr 157410458Sandreas.hansson@arm.com 157510458Sandreas.hansson@arm.com def getValue(self): 157610458Sandreas.hansson@arm.com return self.period.getValue() 157710427Sandreas.hansson@arm.com 157810427Sandreas.hansson@arm.com def config_value(self): 157910427Sandreas.hansson@arm.com return self.period.config_value() 158010427Sandreas.hansson@arm.com 158110427Sandreas.hansson@arm.com def ini_str(self): 158210427Sandreas.hansson@arm.com return self.period.ini_str() 158310427Sandreas.hansson@arm.com 158410427Sandreas.hansson@arm.comclass Voltage(float,ParamValue): 158510427Sandreas.hansson@arm.com cxx_type = 'double' 158610427Sandreas.hansson@arm.com ex_str = "1V" 158710427Sandreas.hansson@arm.com cmd_line_settable = False 158810427Sandreas.hansson@arm.com 158910427Sandreas.hansson@arm.com def __new__(cls, value): 159010427Sandreas.hansson@arm.com # convert to voltage 159110427Sandreas.hansson@arm.com val = convert.toVoltage(value) 159210427Sandreas.hansson@arm.com return super(cls, Voltage).__new__(cls, val) 159310427Sandreas.hansson@arm.com 159410427Sandreas.hansson@arm.com def __call__(self, value): 159510427Sandreas.hansson@arm.com val = convert.toVoltage(value) 159610427Sandreas.hansson@arm.com self.__init__(val) 159710427Sandreas.hansson@arm.com return value 159810427Sandreas.hansson@arm.com 159910427Sandreas.hansson@arm.com def __str__(self): 160010427Sandreas.hansson@arm.com return str(self.getValue()) 160110427Sandreas.hansson@arm.com 160210458Sandreas.hansson@arm.com def getValue(self): 160310458Sandreas.hansson@arm.com value = float(self) 160410458Sandreas.hansson@arm.com return value 160510458Sandreas.hansson@arm.com 160610458Sandreas.hansson@arm.com def ini_str(self): 160710458Sandreas.hansson@arm.com return '%f' % self.getValue() 160810458Sandreas.hansson@arm.com 160910458Sandreas.hansson@arm.com @classmethod 16103101Sstever@eecs.umich.edu def cxx_ini_predecls(cls, code): 16113101Sstever@eecs.umich.edu code('#include <sstream>') 161210267SGeoffrey.Blake@arm.com 161310267SGeoffrey.Blake@arm.com @classmethod 161410267SGeoffrey.Blake@arm.com def cxx_ini_parse(self, code, src, dest, ret): 16153101Sstever@eecs.umich.edu code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 16164167Sbinkertn@umich.edu 16174167Sbinkertn@umich.educlass Current(float, ParamValue): 16183101Sstever@eecs.umich.edu cxx_type = 'double' 16193101Sstever@eecs.umich.edu ex_str = "1mA" 16203101Sstever@eecs.umich.edu cmd_line_settable = False 16213101Sstever@eecs.umich.edu 16223101Sstever@eecs.umich.edu def __new__(cls, value): 162310267SGeoffrey.Blake@arm.com # convert to current 162410267SGeoffrey.Blake@arm.com val = convert.toCurrent(value) 162510267SGeoffrey.Blake@arm.com return super(cls, Current).__new__(cls, val) 162610267SGeoffrey.Blake@arm.com 162710267SGeoffrey.Blake@arm.com def __call__(self, value): 16284762Snate@binkert.org val = convert.toCurrent(value) 16294167Sbinkertn@umich.edu self.__init__(val) 16304167Sbinkertn@umich.edu return value 16314167Sbinkertn@umich.edu 16324762Snate@binkert.org def __str__(self): 16334762Snate@binkert.org return str(self.getValue()) 16344762Snate@binkert.org 16354762Snate@binkert.org def getValue(self): 16364762Snate@binkert.org value = float(self) 16373101Sstever@eecs.umich.edu return value 163810380SAndrew.Bardsley@arm.com 163910380SAndrew.Bardsley@arm.com def ini_str(self): 164010380SAndrew.Bardsley@arm.com return '%f' % self.getValue() 164110458Sandreas.hansson@arm.com 164210458Sandreas.hansson@arm.com @classmethod 164310458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 164410458Sandreas.hansson@arm.com code('#include <sstream>') 164510458Sandreas.hansson@arm.com 164610458Sandreas.hansson@arm.com @classmethod 164710458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 164810458Sandreas.hansson@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 16493101Sstever@eecs.umich.edu 16503101Sstever@eecs.umich.educlass NetworkBandwidth(float,ParamValue): 165110267SGeoffrey.Blake@arm.com cxx_type = 'float' 165210267SGeoffrey.Blake@arm.com ex_str = "1Gbps" 165310267SGeoffrey.Blake@arm.com cmd_line_settable = True 16545469Snate@binkert.org 16557743Sgblack@eecs.umich.edu def __new__(cls, value): 16563102Sstever@eecs.umich.edu # convert to bits per second 16573101Sstever@eecs.umich.edu val = convert.toNetworkBandwidth(value) 16583101Sstever@eecs.umich.edu return super(cls, NetworkBandwidth).__new__(cls, val) 165910267SGeoffrey.Blake@arm.com 166010267SGeoffrey.Blake@arm.com def __str__(self): 166110267SGeoffrey.Blake@arm.com return str(self.val) 166210267SGeoffrey.Blake@arm.com 16633101Sstever@eecs.umich.edu def __call__(self, value): 16644762Snate@binkert.org val = convert.toNetworkBandwidth(value) 16654167Sbinkertn@umich.edu self.__init__(val) 16665468Snate@binkert.org return value 16675468Snate@binkert.org 16685468Snate@binkert.org def getValue(self): 16694167Sbinkertn@umich.edu # convert to seconds per byte 16704762Snate@binkert.org value = 8.0 / float(self) 16714762Snate@binkert.org # convert to ticks per byte 16724762Snate@binkert.org value = ticks.fromSeconds(value) 16734762Snate@binkert.org return float(value) 16744762Snate@binkert.org 16753101Sstever@eecs.umich.edu def ini_str(self): 167610380SAndrew.Bardsley@arm.com return '%f' % self.getValue() 167710380SAndrew.Bardsley@arm.com 167810380SAndrew.Bardsley@arm.com def config_value(self): 167910458Sandreas.hansson@arm.com return '%f' % self.getValue() 168010458Sandreas.hansson@arm.com 168110458Sandreas.hansson@arm.com @classmethod 168210458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 168310458Sandreas.hansson@arm.com code('#include <sstream>') 168410458Sandreas.hansson@arm.com 168510458Sandreas.hansson@arm.com @classmethod 168610458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 16873101Sstever@eecs.umich.edu code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 16883101Sstever@eecs.umich.edu 16893101Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue): 16903101Sstever@eecs.umich.edu cxx_type = 'float' 16913102Sstever@eecs.umich.edu ex_str = "1GB/s" 16923102Sstever@eecs.umich.edu cmd_line_settable = True 16933102Sstever@eecs.umich.edu 16943102Sstever@eecs.umich.edu def __new__(cls, value): 16953102Sstever@eecs.umich.edu # convert to bytes per second 16963102Sstever@eecs.umich.edu val = convert.toMemoryBandwidth(value) 16973102Sstever@eecs.umich.edu return super(cls, MemoryBandwidth).__new__(cls, val) 16983102Sstever@eecs.umich.edu 16993102Sstever@eecs.umich.edu def __call__(self, value): 17003102Sstever@eecs.umich.edu val = convert.toMemoryBandwidth(value) 17013102Sstever@eecs.umich.edu self.__init__(val) 17023102Sstever@eecs.umich.edu return value 17033102Sstever@eecs.umich.edu 17043102Sstever@eecs.umich.edu def getValue(self): 17053102Sstever@eecs.umich.edu # convert to seconds per byte 17063102Sstever@eecs.umich.edu value = float(self) 17073102Sstever@eecs.umich.edu if value: 17083102Sstever@eecs.umich.edu value = 1.0 / float(self) 17093102Sstever@eecs.umich.edu # convert to ticks per byte 17103102Sstever@eecs.umich.edu value = ticks.fromSeconds(value) 17113102Sstever@eecs.umich.edu return float(value) 17124762Snate@binkert.org 171312192Sgabeblack@google.com def ini_str(self): 171412192Sgabeblack@google.com return '%f' % self.getValue() 171512192Sgabeblack@google.com 171612195Sgabeblack@google.com def config_value(self): 171712195Sgabeblack@google.com return '%f' % self.getValue() 171812195Sgabeblack@google.com 17193102Sstever@eecs.umich.edu @classmethod 17203102Sstever@eecs.umich.edu def cxx_ini_predecls(cls, code): 17213102Sstever@eecs.umich.edu code('#include <sstream>') 172210380SAndrew.Bardsley@arm.com 172310380SAndrew.Bardsley@arm.com @classmethod 172410380SAndrew.Bardsley@arm.com def cxx_ini_parse(self, code, src, dest, ret): 17254762Snate@binkert.org code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 17264762Snate@binkert.org 17274762Snate@binkert.org# 17283102Sstever@eecs.umich.edu# "Constants"... handy aliases for various values. 17293102Sstever@eecs.umich.edu# 17303102Sstever@eecs.umich.edu 17313102Sstever@eecs.umich.edu# Special class for NULL pointers. Note the special check in 17323102Sstever@eecs.umich.edu# make_param_value() above that lets these be assigned where a 17333102Sstever@eecs.umich.edu# SimObject is required. 17343101Sstever@eecs.umich.edu# only one copy of a particular node 17353101Sstever@eecs.umich.educlass NullSimObject(object): 17363101Sstever@eecs.umich.edu __metaclass__ = Singleton 17373101Sstever@eecs.umich.edu 17383101Sstever@eecs.umich.edu def __call__(cls): 17393101Sstever@eecs.umich.edu return cls 17403101Sstever@eecs.umich.edu 17413101Sstever@eecs.umich.edu def _instantiate(self, parent = None, path = ''): 17423101Sstever@eecs.umich.edu pass 17433101Sstever@eecs.umich.edu 17443101Sstever@eecs.umich.edu def ini_str(self): 17453101Sstever@eecs.umich.edu return 'Null' 17463101Sstever@eecs.umich.edu 17473101Sstever@eecs.umich.edu def unproxy(self, base): 17483101Sstever@eecs.umich.edu return self 17493101Sstever@eecs.umich.edu 17503101Sstever@eecs.umich.edu def set_path(self, parent, name): 17518839Sandreas.hansson@arm.com pass 17523105Sstever@eecs.umich.edu 17533101Sstever@eecs.umich.edu def __str__(self): 17543101Sstever@eecs.umich.edu return 'Null' 17558839Sandreas.hansson@arm.com 17563101Sstever@eecs.umich.edu def config_value(self): 17573101Sstever@eecs.umich.edu return None 17583105Sstever@eecs.umich.edu 17593101Sstever@eecs.umich.edu def getValue(self): 17603103Sstever@eecs.umich.edu return None 17613105Sstever@eecs.umich.edu 17623103Sstever@eecs.umich.edu# The only instance you'll ever need... 17638840Sandreas.hansson@arm.comNULL = NullSimObject() 17648840Sandreas.hansson@arm.com 17658840Sandreas.hansson@arm.comdef isNullPointer(value): 17668840Sandreas.hansson@arm.com return isinstance(value, NullSimObject) 17678840Sandreas.hansson@arm.com 17683105Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound. 17693105Sstever@eecs.umich.eduMaxAddr = Addr.max 17703105Sstever@eecs.umich.eduMaxTick = Tick.max 17713105Sstever@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr) 17729017Sandreas.hansson@arm.com 17739017Sandreas.hansson@arm.com 17749017Sandreas.hansson@arm.com##################################################################### 17759017Sandreas.hansson@arm.com# 17763105Sstever@eecs.umich.edu# Port objects 17773105Sstever@eecs.umich.edu# 17783105Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system. 17793105Sstever@eecs.umich.edu# 17803105Sstever@eecs.umich.edu##################################################################### 17813105Sstever@eecs.umich.edu 17823105Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a 17833105Sstever@eecs.umich.edu# particular SimObject. 17843105Sstever@eecs.umich.educlass PortRef(object): 17853109Sstever@eecs.umich.edu def __init__(self, simobj, name, role): 17863105Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 17873105Sstever@eecs.umich.edu self.simobj = simobj 17883105Sstever@eecs.umich.edu self.name = name 17893105Sstever@eecs.umich.edu self.role = role 17903105Sstever@eecs.umich.edu self.peer = None # not associated with another port yet 17913105Sstever@eecs.umich.edu self.ccConnected = False # C++ port connection done? 17929014Sandreas.hansson@arm.com self.index = -1 # always -1 for non-vector ports 17939014Sandreas.hansson@arm.com 17943101Sstever@eecs.umich.edu def __str__(self): 17953109Sstever@eecs.umich.edu return '%s.%s' % (self.simobj, self.name) 17963109Sstever@eecs.umich.edu 17973109Sstever@eecs.umich.edu def __len__(self): 17983109Sstever@eecs.umich.edu # Return the number of connected ports, i.e. 0 is we have no 17993109Sstever@eecs.umich.edu # peer and 1 if we do. 18003109Sstever@eecs.umich.edu return int(self.peer != None) 18013109Sstever@eecs.umich.edu 18023109Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 18033109Sstever@eecs.umich.edu def ini_str(self): 18043101Sstever@eecs.umich.edu return str(self.peer) 180510355SGeoffrey.Blake@arm.com 180610355SGeoffrey.Blake@arm.com # for config.json 180710355SGeoffrey.Blake@arm.com def get_config_as_dict(self): 180810355SGeoffrey.Blake@arm.com return {'role' : self.role, 'peer' : str(self.peer)} 180910355SGeoffrey.Blake@arm.com 181010355SGeoffrey.Blake@arm.com def __getattr__(self, attr): 181110355SGeoffrey.Blake@arm.com if attr == 'peerObj': 181210355SGeoffrey.Blake@arm.com # shorthand for proxies 181310355SGeoffrey.Blake@arm.com return self.peer.simobj 181410355SGeoffrey.Blake@arm.com raise AttributeError, "'%s' object has no attribute '%s'" % \ 181510355SGeoffrey.Blake@arm.com (self.__class__.__name__, attr) 181610355SGeoffrey.Blake@arm.com 181710355SGeoffrey.Blake@arm.com # Full connection is symmetric (both ways). Called via 181810355SGeoffrey.Blake@arm.com # SimObject.__setattr__ as a result of a port assignment, e.g., 181910355SGeoffrey.Blake@arm.com # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 182010355SGeoffrey.Blake@arm.com # e.g., "obj1.portA[3] = obj2.portB". 182110355SGeoffrey.Blake@arm.com def connect(self, other): 182210355SGeoffrey.Blake@arm.com if isinstance(other, VectorPortRef): 182310355SGeoffrey.Blake@arm.com # reference to plain VectorPort is implicit append 182410355SGeoffrey.Blake@arm.com other = other._get_next() 182510355SGeoffrey.Blake@arm.com if self.peer and not proxy.isproxy(self.peer): 182610355SGeoffrey.Blake@arm.com fatal("Port %s is already connected to %s, cannot connect %s\n", 182710355SGeoffrey.Blake@arm.com self, self.peer, other); 182810355SGeoffrey.Blake@arm.com self.peer = other 182910355SGeoffrey.Blake@arm.com if proxy.isproxy(other): 183010355SGeoffrey.Blake@arm.com other.set_param_desc(PortParamDesc()) 183110355SGeoffrey.Blake@arm.com elif isinstance(other, PortRef): 183210355SGeoffrey.Blake@arm.com if other.peer is not self: 183310355SGeoffrey.Blake@arm.com other.connect(self) 183410355SGeoffrey.Blake@arm.com else: 18353105Sstever@eecs.umich.edu raise TypeError, \ 18363105Sstever@eecs.umich.edu "assigning non-port reference '%s' to port '%s'" \ 18373105Sstever@eecs.umich.edu % (other, self) 18383101Sstever@eecs.umich.edu 18393105Sstever@eecs.umich.edu # Allow a master/slave port pair to be spliced between 18403105Sstever@eecs.umich.edu # a port and its connected peer. Useful operation for connecting 18413101Sstever@eecs.umich.edu # instrumentation structures into a system when it is necessary 18423105Sstever@eecs.umich.edu # to connect the instrumentation after the full system has been 18433179Sstever@eecs.umich.edu # constructed. 18443105Sstever@eecs.umich.edu def splice(self, new_master_peer, new_slave_peer): 18453105Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 18463101Sstever@eecs.umich.edu if isinstance(new_master_peer, PortRef) and \ 18473101Sstever@eecs.umich.edu isinstance(new_slave_peer, PortRef): 18483105Sstever@eecs.umich.edu old_peer = self.peer 18493105Sstever@eecs.umich.edu if self.role == 'SLAVE': 18503105Sstever@eecs.umich.edu self.peer = new_master_peer 18513105Sstever@eecs.umich.edu old_peer.peer = new_slave_peer 18523105Sstever@eecs.umich.edu new_master_peer.connect(self) 18533105Sstever@eecs.umich.edu new_slave_peer.connect(old_peer) 18543105Sstever@eecs.umich.edu elif self.role == 'MASTER': 18553105Sstever@eecs.umich.edu self.peer = new_slave_peer 18563105Sstever@eecs.umich.edu old_peer.peer = new_master_peer 18573105Sstever@eecs.umich.edu new_slave_peer.connect(self) 18583105Sstever@eecs.umich.edu new_master_peer.connect(old_peer) 18593101Sstever@eecs.umich.edu else: 18603101Sstever@eecs.umich.edu panic("Port %s has unknown role, "+\ 186111802Sandreas.sandberg@arm.com "cannot splice in new peers\n", self) 18624762Snate@binkert.org else: 18638839Sandreas.hansson@arm.com raise TypeError, \ 18648839Sandreas.hansson@arm.com "Splicing non-port references '%s','%s' to port '%s'"\ 18658839Sandreas.hansson@arm.com % (new_peer, peers_new_peer, self) 18668839Sandreas.hansson@arm.com else: 18673101Sstever@eecs.umich.edu fatal("Port %s not connected, cannot splice in new peers\n", self) 18683101Sstever@eecs.umich.edu 18693101Sstever@eecs.umich.edu def clone(self, simobj, memo): 18705578SSteve.Reinhardt@amd.com if memo.has_key(self): 18715578SSteve.Reinhardt@amd.com return memo[self] 18728839Sandreas.hansson@arm.com newRef = copy.copy(self) 18738839Sandreas.hansson@arm.com memo[self] = newRef 18748839Sandreas.hansson@arm.com newRef.simobj = simobj 18758839Sandreas.hansson@arm.com assert(isSimObject(newRef.simobj)) 18768839Sandreas.hansson@arm.com if self.peer and not proxy.isproxy(self.peer): 18778839Sandreas.hansson@arm.com peerObj = self.peer.simobj(_memo=memo) 18788839Sandreas.hansson@arm.com newRef.peer = self.peer.clone(peerObj, memo) 18797526Ssteve.reinhardt@amd.com assert(not isinstance(newRef.peer, VectorPortRef)) 18808839Sandreas.hansson@arm.com return newRef 18817526Ssteve.reinhardt@amd.com 18827526Ssteve.reinhardt@amd.com def unproxy(self, simobj): 18837526Ssteve.reinhardt@amd.com assert(simobj is self.simobj) 18847526Ssteve.reinhardt@amd.com if proxy.isproxy(self.peer): 18857526Ssteve.reinhardt@amd.com try: 18867526Ssteve.reinhardt@amd.com realPeer = self.peer.unproxy(self.simobj) 18877526Ssteve.reinhardt@amd.com except: 18883101Sstever@eecs.umich.edu print "Error in unproxying port '%s' of %s" % \ 18893101Sstever@eecs.umich.edu (self.name, self.simobj.path()) 18903101Sstever@eecs.umich.edu raise 18913105Sstever@eecs.umich.edu self.connect(realPeer) 18923105Sstever@eecs.umich.edu 18933105Sstever@eecs.umich.edu # Call C++ to create corresponding port connection between C++ objects 18948839Sandreas.hansson@arm.com def ccConnect(self): 18958839Sandreas.hansson@arm.com from m5.internal.pyobject import connectPorts 18963105Sstever@eecs.umich.edu 18973105Sstever@eecs.umich.edu if self.role == 'SLAVE': 18983105Sstever@eecs.umich.edu # do nothing and let the master take care of it 18993105Sstever@eecs.umich.edu return 19003105Sstever@eecs.umich.edu 19013105Sstever@eecs.umich.edu if self.ccConnected: # already done this 19023105Sstever@eecs.umich.edu return 19033105Sstever@eecs.umich.edu peer = self.peer 19048839Sandreas.hansson@arm.com if not self.peer: # nothing to connect to 19053105Sstever@eecs.umich.edu return 19063105Sstever@eecs.umich.edu 19073105Sstever@eecs.umich.edu # check that we connect a master to a slave 19088839Sandreas.hansson@arm.com if self.role == peer.role: 19093105Sstever@eecs.umich.edu raise TypeError, \ 19103105Sstever@eecs.umich.edu "cannot connect '%s' and '%s' due to identical role '%s'" \ 19113109Sstever@eecs.umich.edu % (peer, self, self.role) 19123109Sstever@eecs.umich.edu 19133109Sstever@eecs.umich.edu try: 19148840Sandreas.hansson@arm.com # self is always the master and peer the slave 19158840Sandreas.hansson@arm.com connectPorts(self.simobj.getCCObject(), self.name, self.index, 19168840Sandreas.hansson@arm.com peer.simobj.getCCObject(), peer.name, peer.index) 19178840Sandreas.hansson@arm.com except: 19188840Sandreas.hansson@arm.com print "Error connecting port %s.%s to %s.%s" % \ 19193105Sstever@eecs.umich.edu (self.simobj.path(), self.name, 19203105Sstever@eecs.umich.edu peer.simobj.path(), peer.name) 19213105Sstever@eecs.umich.edu raise 19223105Sstever@eecs.umich.edu self.ccConnected = True 19239017Sandreas.hansson@arm.com peer.ccConnected = True 19249017Sandreas.hansson@arm.com 19259017Sandreas.hansson@arm.com# A reference to an individual element of a VectorPort... much like a 19269017Sandreas.hansson@arm.com# PortRef, but has an index. 19279017Sandreas.hansson@arm.comclass VectorPortElementRef(PortRef): 19283105Sstever@eecs.umich.edu def __init__(self, simobj, name, role, index): 19293105Sstever@eecs.umich.edu PortRef.__init__(self, simobj, name, role) 19303105Sstever@eecs.umich.edu self.index = index 19313105Sstever@eecs.umich.edu 19323105Sstever@eecs.umich.edu def __str__(self): 19338839Sandreas.hansson@arm.com return '%s.%s[%d]' % (self.simobj, self.name, self.index) 19343105Sstever@eecs.umich.edu 19353105Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element). 19363105Sstever@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances. 19373105Sstever@eecs.umich.educlass VectorPortRef(object): 19383105Sstever@eecs.umich.edu def __init__(self, simobj, name, role): 19393105Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 19403105Sstever@eecs.umich.edu self.simobj = simobj 19413105Sstever@eecs.umich.edu self.name = name 19423105Sstever@eecs.umich.edu self.role = role 19433105Sstever@eecs.umich.edu self.elements = [] 19443105Sstever@eecs.umich.edu 19453105Sstever@eecs.umich.edu def __str__(self): 19463105Sstever@eecs.umich.edu return '%s.%s[:]' % (self.simobj, self.name) 19473109Sstever@eecs.umich.edu 19483109Sstever@eecs.umich.edu def __len__(self): 19493109Sstever@eecs.umich.edu # Return the number of connected peers, corresponding the the 19503109Sstever@eecs.umich.edu # length of the elements. 19513109Sstever@eecs.umich.edu return len(self.elements) 19523109Sstever@eecs.umich.edu 19533109Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 19543109Sstever@eecs.umich.edu def ini_str(self): 19553109Sstever@eecs.umich.edu return ' '.join([el.ini_str() for el in self.elements]) 19563109Sstever@eecs.umich.edu 19573109Sstever@eecs.umich.edu # for config.json 19583109Sstever@eecs.umich.edu def get_config_as_dict(self): 19593109Sstever@eecs.umich.edu return {'role' : self.role, 19603109Sstever@eecs.umich.edu 'peer' : [el.ini_str() for el in self.elements]} 19613109Sstever@eecs.umich.edu 19623109Sstever@eecs.umich.edu def __getitem__(self, key): 19633109Sstever@eecs.umich.edu if not isinstance(key, int): 19643109Sstever@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 19653109Sstever@eecs.umich.edu if key >= len(self.elements): 19663105Sstever@eecs.umich.edu # need to extend list 19673105Sstever@eecs.umich.edu ext = [VectorPortElementRef(self.simobj, self.name, self.role, i) 19683105Sstever@eecs.umich.edu for i in range(len(self.elements), key+1)] 19693105Sstever@eecs.umich.edu self.elements.extend(ext) 19703105Sstever@eecs.umich.edu return self.elements[key] 19713105Sstever@eecs.umich.edu 19723105Sstever@eecs.umich.edu def _get_next(self): 19733101Sstever@eecs.umich.edu return self[len(self.elements)] 19743101Sstever@eecs.umich.edu 19753101Sstever@eecs.umich.edu def __setitem__(self, key, value): 19763101Sstever@eecs.umich.edu if not isinstance(key, int): 19773101Sstever@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 19783101Sstever@eecs.umich.edu self[key].connect(value) 19793105Sstever@eecs.umich.edu 19808839Sandreas.hansson@arm.com def connect(self, other): 19813101Sstever@eecs.umich.edu if isinstance(other, (list, tuple)): 19823101Sstever@eecs.umich.edu # Assign list of port refs to vector port. 19833101Sstever@eecs.umich.edu # For now, append them... not sure if that's the right semantics 19843105Sstever@eecs.umich.edu # or if it should replace the current vector. 19853105Sstever@eecs.umich.edu for ref in other: 19863101Sstever@eecs.umich.edu self._get_next().connect(ref) 19878840Sandreas.hansson@arm.com else: 19888840Sandreas.hansson@arm.com # scalar assignment to plain VectorPort is implicit append 19898840Sandreas.hansson@arm.com self._get_next().connect(other) 19908840Sandreas.hansson@arm.com 19918840Sandreas.hansson@arm.com def clone(self, simobj, memo): 199211988Sandreas.sandberg@arm.com if memo.has_key(self): 199311988Sandreas.sandberg@arm.com return memo[self] 199411988Sandreas.sandberg@arm.com newRef = copy.copy(self) 19958840Sandreas.hansson@arm.com memo[self] = newRef 19968840Sandreas.hansson@arm.com newRef.simobj = simobj 19978840Sandreas.hansson@arm.com assert(isSimObject(newRef.simobj)) 19988840Sandreas.hansson@arm.com newRef.elements = [el.clone(simobj, memo) for el in self.elements] 19998840Sandreas.hansson@arm.com return newRef 20008840Sandreas.hansson@arm.com 20018839Sandreas.hansson@arm.com def unproxy(self, simobj): 20028839Sandreas.hansson@arm.com [el.unproxy(simobj) for el in self.elements] 20038839Sandreas.hansson@arm.com 20048839Sandreas.hansson@arm.com def ccConnect(self): 20058839Sandreas.hansson@arm.com [el.ccConnect() for el in self.elements] 20068839Sandreas.hansson@arm.com 20078839Sandreas.hansson@arm.com# Port description object. Like a ParamDesc object, this represents a 20088839Sandreas.hansson@arm.com# logical port in the SimObject class, not a particular port on a 20098839Sandreas.hansson@arm.com# SimObject instance. The latter are represented by PortRef objects. 20108839Sandreas.hansson@arm.comclass Port(object): 20118839Sandreas.hansson@arm.com # Generate a PortRef for this port on the given SimObject with the 20128839Sandreas.hansson@arm.com # given name 20138839Sandreas.hansson@arm.com def makeRef(self, simobj): 20148839Sandreas.hansson@arm.com return PortRef(simobj, self.name, self.role) 20158839Sandreas.hansson@arm.com 20168839Sandreas.hansson@arm.com # Connect an instance of this port (on the given SimObject with 20178839Sandreas.hansson@arm.com # the given name) with the port described by the supplied PortRef 20188839Sandreas.hansson@arm.com def connect(self, simobj, ref): 20193101Sstever@eecs.umich.edu self.makeRef(simobj).connect(ref) 202010405Sandreas.hansson@arm.com 20213101Sstever@eecs.umich.edu # No need for any pre-declarations at the moment as we merely rely 20223105Sstever@eecs.umich.edu # on an unsigned int. 20233101Sstever@eecs.umich.edu def cxx_predecls(self, code): 20243101Sstever@eecs.umich.edu pass 20253105Sstever@eecs.umich.edu 20268839Sandreas.hansson@arm.com # Declare an unsigned int with the same name as the port, that 20278839Sandreas.hansson@arm.com # will eventually hold the number of connected ports (and thus the 20288839Sandreas.hansson@arm.com # number of elements for a VectorPort). 20298839Sandreas.hansson@arm.com def cxx_decl(self, code): 20308839Sandreas.hansson@arm.com code('unsigned int port_${{self.name}}_connection_count;') 20318839Sandreas.hansson@arm.com 20328839Sandreas.hansson@arm.comclass MasterPort(Port): 20338839Sandreas.hansson@arm.com # MasterPort("description") 20348839Sandreas.hansson@arm.com def __init__(self, *args): 20358839Sandreas.hansson@arm.com if len(args) == 1: 20368839Sandreas.hansson@arm.com self.desc = args[0] 20378839Sandreas.hansson@arm.com self.role = 'MASTER' 20388839Sandreas.hansson@arm.com else: 20398839Sandreas.hansson@arm.com raise TypeError, 'wrong number of arguments' 20408839Sandreas.hansson@arm.com 20418839Sandreas.hansson@arm.comclass SlavePort(Port): 20428839Sandreas.hansson@arm.com # SlavePort("description") 20438839Sandreas.hansson@arm.com def __init__(self, *args): 20448839Sandreas.hansson@arm.com if len(args) == 1: 20458839Sandreas.hansson@arm.com self.desc = args[0] 20468839Sandreas.hansson@arm.com self.role = 'SLAVE' 20473105Sstever@eecs.umich.edu else: 20483109Sstever@eecs.umich.edu raise TypeError, 'wrong number of arguments' 20493109Sstever@eecs.umich.edu 20503109Sstever@eecs.umich.edu# VectorPort description object. Like Port, but represents a vector 20513109Sstever@eecs.umich.edu# of connections (e.g., as on a XBar). 20523109Sstever@eecs.umich.educlass VectorPort(Port): 20533109Sstever@eecs.umich.edu def __init__(self, *args): 20543109Sstever@eecs.umich.edu self.isVec = True 20553109Sstever@eecs.umich.edu 20563105Sstever@eecs.umich.edu def makeRef(self, simobj): 20576654Snate@binkert.org return VectorPortRef(simobj, self.name, self.role) 20586654Snate@binkert.org 20596654Snate@binkert.orgclass VectorMasterPort(VectorPort): 20606654Snate@binkert.org # VectorMasterPort("description") 20616654Snate@binkert.org def __init__(self, *args): 20626654Snate@binkert.org if len(args) == 1: 20636654Snate@binkert.org self.desc = args[0] 20646654Snate@binkert.org self.role = 'MASTER' 20656654Snate@binkert.org VectorPort.__init__(self, *args) 20663101Sstever@eecs.umich.edu else: 20673101Sstever@eecs.umich.edu raise TypeError, 'wrong number of arguments' 20683101Sstever@eecs.umich.edu 20693101Sstever@eecs.umich.educlass VectorSlavePort(VectorPort): 20703101Sstever@eecs.umich.edu # VectorSlavePort("description") 20713101Sstever@eecs.umich.edu def __init__(self, *args): 20727777Sgblack@eecs.umich.edu if len(args) == 1: 20733101Sstever@eecs.umich.edu self.desc = args[0] 20749827Sakash.bagdia@arm.com self.role = 'SLAVE' 20753101Sstever@eecs.umich.edu VectorPort.__init__(self, *args) 20769232Sandreas.hansson@arm.com else: 20773101Sstever@eecs.umich.edu raise TypeError, 'wrong number of arguments' 20783885Sbinkertn@umich.edu 20793102Sstever@eecs.umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 20808839Sandreas.hansson@arm.com# proxy objects (via set_param_desc()) so that proxy error messages 20818839Sandreas.hansson@arm.com# make sense. 20826654Snate@binkert.orgclass PortParamDesc(object): 20836654Snate@binkert.org __metaclass__ = Singleton 2084 2085 ptype_str = 'Port' 2086 ptype = Port 2087 2088baseEnums = allEnums.copy() 2089baseParams = allParams.copy() 2090 2091def clear(): 2092 global allEnums, allParams 2093 2094 allEnums = baseEnums.copy() 2095 allParams = baseParams.copy() 2096 2097__all__ = ['Param', 'VectorParam', 2098 'Enum', 'Bool', 'String', 'Float', 2099 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 2100 'Int32', 'UInt32', 'Int64', 'UInt64', 2101 'Counter', 'Addr', 'Tick', 'Percent', 2102 'TcpPort', 'UdpPort', 'EthernetAddr', 2103 'IpAddress', 'IpNetmask', 'IpWithPort', 2104 'MemorySize', 'MemorySize32', 2105 'Latency', 'Frequency', 'Clock', 'Voltage', 2106 'NetworkBandwidth', 'MemoryBandwidth', 2107 'AddrRange', 2108 'MaxAddr', 'MaxTick', 'AllMemory', 2109 'Time', 2110 'NextEthernetAddr', 'NULL', 2111 'MasterPort', 'SlavePort', 2112 'VectorMasterPort', 'VectorSlavePort'] 2113 2114import SimObject 2115