params.py revision 12196
111988Sandreas.sandberg@arm.com# Copyright (c) 2012-2014, 2017 ARM Limited 28839Sandreas.hansson@arm.com# All rights reserved. 38839Sandreas.hansson@arm.com# 48839Sandreas.hansson@arm.com# The license below extends only to copyright in the software and shall 58839Sandreas.hansson@arm.com# not be construed as granting a license to any other intellectual 68839Sandreas.hansson@arm.com# property including but not limited to intellectual property relating 78839Sandreas.hansson@arm.com# to a hardware implementation of the functionality of the software 88839Sandreas.hansson@arm.com# licensed hereunder. You may use the software subject to the license 98839Sandreas.hansson@arm.com# terms below provided that you ensure that this notice is replicated 108839Sandreas.hansson@arm.com# unmodified and in its entirety in all distributions of the software, 118839Sandreas.hansson@arm.com# modified or unmodified, in source code or in binary form. 128839Sandreas.hansson@arm.com# 133101Sstever@eecs.umich.edu# Copyright (c) 2004-2006 The Regents of The University of Michigan 148579Ssteve.reinhardt@amd.com# Copyright (c) 2010-2011 Advanced Micro Devices, Inc. 153101Sstever@eecs.umich.edu# All rights reserved. 163101Sstever@eecs.umich.edu# 173101Sstever@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 183101Sstever@eecs.umich.edu# modification, are permitted provided that the following conditions are 193101Sstever@eecs.umich.edu# met: redistributions of source code must retain the above copyright 203101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 213101Sstever@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 223101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 233101Sstever@eecs.umich.edu# documentation and/or other materials provided with the distribution; 243101Sstever@eecs.umich.edu# neither the name of the copyright holders nor the names of its 253101Sstever@eecs.umich.edu# contributors may be used to endorse or promote products derived from 263101Sstever@eecs.umich.edu# this software without specific prior written permission. 273101Sstever@eecs.umich.edu# 283101Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 293101Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 303101Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 313101Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 323101Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 333101Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 343101Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 353101Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 363101Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 373101Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 383101Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 393101Sstever@eecs.umich.edu# 403101Sstever@eecs.umich.edu# Authors: Steve Reinhardt 413101Sstever@eecs.umich.edu# Nathan Binkert 427778Sgblack@eecs.umich.edu# Gabe Black 438839Sandreas.hansson@arm.com# Andreas Hansson 443101Sstever@eecs.umich.edu 453101Sstever@eecs.umich.edu##################################################################### 463101Sstever@eecs.umich.edu# 473101Sstever@eecs.umich.edu# Parameter description classes 483101Sstever@eecs.umich.edu# 493101Sstever@eecs.umich.edu# The _params dictionary in each class maps parameter names to either 503101Sstever@eecs.umich.edu# a Param or a VectorParam object. These objects contain the 513101Sstever@eecs.umich.edu# parameter description string, the parameter type, and the default 523101Sstever@eecs.umich.edu# value (if any). The convert() method on these objects is used to 533101Sstever@eecs.umich.edu# force whatever value is assigned to the parameter to the appropriate 543101Sstever@eecs.umich.edu# type. 553101Sstever@eecs.umich.edu# 563101Sstever@eecs.umich.edu# Note that the default values are loaded into the class's attribute 573101Sstever@eecs.umich.edu# space when the parameter dictionary is initialized (in 583101Sstever@eecs.umich.edu# MetaSimObject._new_param()); after that point they aren't used. 593101Sstever@eecs.umich.edu# 603101Sstever@eecs.umich.edu##################################################################### 613101Sstever@eecs.umich.edu 623885Sbinkertn@umich.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 @classmethod 10611988Sandreas.sandberg@arm.com def pybind_predecls(cls, code): 10711988Sandreas.sandberg@arm.com cls.cxx_predecls(code) 10811988Sandreas.sandberg@arm.com 1093101Sstever@eecs.umich.edu # default for printing to .ini file is regular string conversion. 1103101Sstever@eecs.umich.edu # will be overridden in some cases 1113101Sstever@eecs.umich.edu def ini_str(self): 1123101Sstever@eecs.umich.edu return str(self) 1133101Sstever@eecs.umich.edu 11410380SAndrew.Bardsley@arm.com # default for printing to .json file is regular string conversion. 11510380SAndrew.Bardsley@arm.com # will be overridden in some cases, mostly to use native Python 11610380SAndrew.Bardsley@arm.com # types where there are similar JSON types 11710380SAndrew.Bardsley@arm.com def config_value(self): 11810380SAndrew.Bardsley@arm.com return str(self) 11910380SAndrew.Bardsley@arm.com 12010458Sandreas.hansson@arm.com # Prerequisites for .ini parsing with cxx_ini_parse 12110458Sandreas.hansson@arm.com @classmethod 12210458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 12310458Sandreas.hansson@arm.com pass 12410458Sandreas.hansson@arm.com 12510458Sandreas.hansson@arm.com # parse a .ini file entry for this param from string expression 12610458Sandreas.hansson@arm.com # src into lvalue dest (of the param's C++ type) 12710458Sandreas.hansson@arm.com @classmethod 12810458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 12910458Sandreas.hansson@arm.com code('// Unhandled param type: %s' % cls.__name__) 13010458Sandreas.hansson@arm.com code('%s false;' % ret) 13110458Sandreas.hansson@arm.com 1323101Sstever@eecs.umich.edu # allows us to blithely call unproxy() on things without checking 1333101Sstever@eecs.umich.edu # if they're really proxies or not 1343101Sstever@eecs.umich.edu def unproxy(self, base): 1353101Sstever@eecs.umich.edu return self 1363101Sstever@eecs.umich.edu 13710267SGeoffrey.Blake@arm.com # Produce a human readable version of the stored value 13810267SGeoffrey.Blake@arm.com def pretty_print(self, value): 13910267SGeoffrey.Blake@arm.com return str(value) 14010267SGeoffrey.Blake@arm.com 1413101Sstever@eecs.umich.edu# Regular parameter description. 1423101Sstever@eecs.umich.educlass ParamDesc(object): 1433101Sstever@eecs.umich.edu def __init__(self, ptype_str, ptype, *args, **kwargs): 1443101Sstever@eecs.umich.edu self.ptype_str = ptype_str 1453101Sstever@eecs.umich.edu # remember ptype only if it is provided 1463101Sstever@eecs.umich.edu if ptype != None: 1473101Sstever@eecs.umich.edu self.ptype = ptype 1483101Sstever@eecs.umich.edu 1493101Sstever@eecs.umich.edu if args: 1503101Sstever@eecs.umich.edu if len(args) == 1: 1513101Sstever@eecs.umich.edu self.desc = args[0] 1523101Sstever@eecs.umich.edu elif len(args) == 2: 1533101Sstever@eecs.umich.edu self.default = args[0] 1543101Sstever@eecs.umich.edu self.desc = args[1] 1553101Sstever@eecs.umich.edu else: 1563101Sstever@eecs.umich.edu raise TypeError, 'too many arguments' 1573101Sstever@eecs.umich.edu 1583101Sstever@eecs.umich.edu if kwargs.has_key('desc'): 1593101Sstever@eecs.umich.edu assert(not hasattr(self, 'desc')) 1603101Sstever@eecs.umich.edu self.desc = kwargs['desc'] 1613101Sstever@eecs.umich.edu del kwargs['desc'] 1623101Sstever@eecs.umich.edu 1633101Sstever@eecs.umich.edu if kwargs.has_key('default'): 1643101Sstever@eecs.umich.edu assert(not hasattr(self, 'default')) 1653101Sstever@eecs.umich.edu self.default = kwargs['default'] 1663101Sstever@eecs.umich.edu del kwargs['default'] 1673101Sstever@eecs.umich.edu 1683101Sstever@eecs.umich.edu if kwargs: 1693101Sstever@eecs.umich.edu raise TypeError, 'extra unknown kwargs %s' % kwargs 1703101Sstever@eecs.umich.edu 1713101Sstever@eecs.umich.edu if not hasattr(self, 'desc'): 1723101Sstever@eecs.umich.edu raise TypeError, 'desc attribute missing' 1733101Sstever@eecs.umich.edu 1743101Sstever@eecs.umich.edu def __getattr__(self, attr): 1753101Sstever@eecs.umich.edu if attr == 'ptype': 1765033Smilesck@eecs.umich.edu ptype = SimObject.allClasses[self.ptype_str] 1776656Snate@binkert.org assert isSimObjectClass(ptype) 1785033Smilesck@eecs.umich.edu self.ptype = ptype 1795033Smilesck@eecs.umich.edu return ptype 1805033Smilesck@eecs.umich.edu 1813101Sstever@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 1823101Sstever@eecs.umich.edu (type(self).__name__, attr) 1833101Sstever@eecs.umich.edu 18410267SGeoffrey.Blake@arm.com def example_str(self): 18510267SGeoffrey.Blake@arm.com if hasattr(self.ptype, "ex_str"): 18610267SGeoffrey.Blake@arm.com return self.ptype.ex_str 18710267SGeoffrey.Blake@arm.com else: 18810267SGeoffrey.Blake@arm.com return self.ptype_str 18910267SGeoffrey.Blake@arm.com 19010267SGeoffrey.Blake@arm.com # Is the param available to be exposed on the command line 19110267SGeoffrey.Blake@arm.com def isCmdLineSettable(self): 19210267SGeoffrey.Blake@arm.com if hasattr(self.ptype, "cmd_line_settable"): 19310267SGeoffrey.Blake@arm.com return self.ptype.cmd_line_settable 19410267SGeoffrey.Blake@arm.com else: 19510267SGeoffrey.Blake@arm.com return False 19610267SGeoffrey.Blake@arm.com 1973101Sstever@eecs.umich.edu def convert(self, value): 1983101Sstever@eecs.umich.edu if isinstance(value, proxy.BaseProxy): 1993101Sstever@eecs.umich.edu value.set_param_desc(self) 2003101Sstever@eecs.umich.edu return value 2013101Sstever@eecs.umich.edu if not hasattr(self, 'ptype') and isNullPointer(value): 2023101Sstever@eecs.umich.edu # deferred evaluation of SimObject; continue to defer if 2033101Sstever@eecs.umich.edu # we're just assigning a null pointer 2043101Sstever@eecs.umich.edu return value 2053101Sstever@eecs.umich.edu if isinstance(value, self.ptype): 2063101Sstever@eecs.umich.edu return value 2073102Sstever@eecs.umich.edu if isNullPointer(value) and isSimObjectClass(self.ptype): 2083101Sstever@eecs.umich.edu return value 2093101Sstever@eecs.umich.edu return self.ptype(value) 2103101Sstever@eecs.umich.edu 21110267SGeoffrey.Blake@arm.com def pretty_print(self, value): 21210267SGeoffrey.Blake@arm.com if isinstance(value, proxy.BaseProxy): 21310267SGeoffrey.Blake@arm.com return str(value) 21410267SGeoffrey.Blake@arm.com if isNullPointer(value): 21510267SGeoffrey.Blake@arm.com return NULL 21610267SGeoffrey.Blake@arm.com return self.ptype(value).pretty_print(value) 21710267SGeoffrey.Blake@arm.com 2187673Snate@binkert.org def cxx_predecls(self, code): 2198607Sgblack@eecs.umich.edu code('#include <cstddef>') 2207673Snate@binkert.org self.ptype.cxx_predecls(code) 2213101Sstever@eecs.umich.edu 22211988Sandreas.sandberg@arm.com def pybind_predecls(self, code): 22311988Sandreas.sandberg@arm.com self.ptype.pybind_predecls(code) 22411988Sandreas.sandberg@arm.com 2257673Snate@binkert.org def cxx_decl(self, code): 2267673Snate@binkert.org code('${{self.ptype.cxx_type}} ${{self.name}};') 2273101Sstever@eecs.umich.edu 2283101Sstever@eecs.umich.edu# Vector-valued parameter description. Just like ParamDesc, except 2293101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a 2303101Sstever@eecs.umich.edu# single value. 2313101Sstever@eecs.umich.edu 2323101Sstever@eecs.umich.educlass VectorParamValue(list): 2335033Smilesck@eecs.umich.edu __metaclass__ = MetaParamValue 2345475Snate@binkert.org def __setattr__(self, attr, value): 2355475Snate@binkert.org raise AttributeError, \ 2365475Snate@binkert.org "Not allowed to set %s on '%s'" % (attr, type(self).__name__) 2375475Snate@binkert.org 23810380SAndrew.Bardsley@arm.com def config_value(self): 23910380SAndrew.Bardsley@arm.com return [v.config_value() for v in self] 24010380SAndrew.Bardsley@arm.com 2413101Sstever@eecs.umich.edu def ini_str(self): 2423101Sstever@eecs.umich.edu return ' '.join([v.ini_str() for v in self]) 2433101Sstever@eecs.umich.edu 2444762Snate@binkert.org def getValue(self): 2454762Snate@binkert.org return [ v.getValue() for v in self ] 2464762Snate@binkert.org 2473101Sstever@eecs.umich.edu def unproxy(self, base): 24812050Snikos.nikoleris@arm.com if len(self) == 1 and isinstance(self[0], proxy.BaseProxy): 24912050Snikos.nikoleris@arm.com # The value is a proxy (e.g. Parent.any, Parent.all or 25012050Snikos.nikoleris@arm.com # Parent.x) therefore try resolve it 2518459SAli.Saidi@ARM.com return self[0].unproxy(base) 2528459SAli.Saidi@ARM.com else: 25312050Snikos.nikoleris@arm.com return [v.unproxy(base) for v in self] 2543101Sstever@eecs.umich.edu 2557528Ssteve.reinhardt@amd.comclass SimObjectVector(VectorParamValue): 2567528Ssteve.reinhardt@amd.com # support clone operation 2577528Ssteve.reinhardt@amd.com def __call__(self, **kwargs): 2587528Ssteve.reinhardt@amd.com return SimObjectVector([v(**kwargs) for v in self]) 2597528Ssteve.reinhardt@amd.com 2607528Ssteve.reinhardt@amd.com def clear_parent(self, old_parent): 2613101Sstever@eecs.umich.edu for v in self: 2627528Ssteve.reinhardt@amd.com v.clear_parent(old_parent) 2637528Ssteve.reinhardt@amd.com 2647528Ssteve.reinhardt@amd.com def set_parent(self, parent, name): 2657528Ssteve.reinhardt@amd.com if len(self) == 1: 2667528Ssteve.reinhardt@amd.com self[0].set_parent(parent, name) 2677528Ssteve.reinhardt@amd.com else: 2687528Ssteve.reinhardt@amd.com width = int(math.ceil(math.log(len(self))/math.log(10))) 2697528Ssteve.reinhardt@amd.com for i,v in enumerate(self): 2707528Ssteve.reinhardt@amd.com v.set_parent(parent, "%s%0*d" % (name, width, i)) 2717528Ssteve.reinhardt@amd.com 2728321Ssteve.reinhardt@amd.com def has_parent(self): 27312194Sgabeblack@google.com return any([e.has_parent() for e in self if not isNullPointer(e)]) 2747528Ssteve.reinhardt@amd.com 2757528Ssteve.reinhardt@amd.com # return 'cpu0 cpu1' etc. for print_ini() 2767528Ssteve.reinhardt@amd.com def get_name(self): 2777528Ssteve.reinhardt@amd.com return ' '.join([v._name for v in self]) 2787528Ssteve.reinhardt@amd.com 2797528Ssteve.reinhardt@amd.com # By iterating through the constituent members of the vector here 2807528Ssteve.reinhardt@amd.com # we can nicely handle iterating over all a SimObject's children 2817528Ssteve.reinhardt@amd.com # without having to provide lots of special functions on 2827528Ssteve.reinhardt@amd.com # SimObjectVector directly. 2837528Ssteve.reinhardt@amd.com def descendants(self): 2847528Ssteve.reinhardt@amd.com for v in self: 2857528Ssteve.reinhardt@amd.com for obj in v.descendants(): 2867528Ssteve.reinhardt@amd.com yield obj 2873101Sstever@eecs.umich.edu 2888664SAli.Saidi@ARM.com def get_config_as_dict(self): 2898664SAli.Saidi@ARM.com a = [] 2908664SAli.Saidi@ARM.com for v in self: 2918664SAli.Saidi@ARM.com a.append(v.get_config_as_dict()) 2928664SAli.Saidi@ARM.com return a 2938664SAli.Saidi@ARM.com 2949953Sgeoffrey.blake@arm.com # If we are replacing an item in the vector, make sure to set the 2959953Sgeoffrey.blake@arm.com # parent reference of the new SimObject to be the same as the parent 2969953Sgeoffrey.blake@arm.com # of the SimObject being replaced. Useful to have if we created 2979953Sgeoffrey.blake@arm.com # a SimObjectVector of temporary objects that will be modified later in 2989953Sgeoffrey.blake@arm.com # configuration scripts. 2999953Sgeoffrey.blake@arm.com def __setitem__(self, key, value): 3009953Sgeoffrey.blake@arm.com val = self[key] 3019953Sgeoffrey.blake@arm.com if value.has_parent(): 3029953Sgeoffrey.blake@arm.com warn("SimObject %s already has a parent" % value.get_name() +\ 3039953Sgeoffrey.blake@arm.com " that is being overwritten by a SimObjectVector") 3049953Sgeoffrey.blake@arm.com value.set_parent(val.get_parent(), val._name) 3059953Sgeoffrey.blake@arm.com super(SimObjectVector, self).__setitem__(key, value) 3069953Sgeoffrey.blake@arm.com 30710267SGeoffrey.Blake@arm.com # Enumerate the params of each member of the SimObject vector. Creates 30810267SGeoffrey.Blake@arm.com # strings that will allow indexing into the vector by the python code and 30910267SGeoffrey.Blake@arm.com # allow it to be specified on the command line. 31010267SGeoffrey.Blake@arm.com def enumerateParams(self, flags_dict = {}, 31110267SGeoffrey.Blake@arm.com cmd_line_str = "", 31210267SGeoffrey.Blake@arm.com access_str = ""): 31310267SGeoffrey.Blake@arm.com if hasattr(self, "_paramEnumed"): 31410267SGeoffrey.Blake@arm.com print "Cycle detected enumerating params at %s?!" % (cmd_line_str) 31510267SGeoffrey.Blake@arm.com else: 31610267SGeoffrey.Blake@arm.com x = 0 31710267SGeoffrey.Blake@arm.com for vals in self: 31810267SGeoffrey.Blake@arm.com # Each entry in the SimObjectVector should be an 31910267SGeoffrey.Blake@arm.com # instance of a SimObject 32010267SGeoffrey.Blake@arm.com flags_dict = vals.enumerateParams(flags_dict, 32110267SGeoffrey.Blake@arm.com cmd_line_str + "%d." % x, 32210267SGeoffrey.Blake@arm.com access_str + "[%d]." % x) 32310267SGeoffrey.Blake@arm.com x = x + 1 32410267SGeoffrey.Blake@arm.com 32510267SGeoffrey.Blake@arm.com return flags_dict 32610267SGeoffrey.Blake@arm.com 3273101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc): 3283101Sstever@eecs.umich.edu # Convert assigned value to appropriate type. If the RHS is not a 3293101Sstever@eecs.umich.edu # list or tuple, it generates a single-element list. 3303101Sstever@eecs.umich.edu def convert(self, value): 3313101Sstever@eecs.umich.edu if isinstance(value, (list, tuple)): 3323101Sstever@eecs.umich.edu # list: coerce each element into new list 3333101Sstever@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) for v in value ] 33410364SGeoffrey.Blake@arm.com elif isinstance(value, str): 33510364SGeoffrey.Blake@arm.com # If input is a csv string 33610364SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) \ 33710364SGeoffrey.Blake@arm.com for v in value.strip('[').strip(']').split(',') ] 3383101Sstever@eecs.umich.edu else: 3394762Snate@binkert.org # singleton: coerce to a single-element list 3404762Snate@binkert.org tmp_list = [ ParamDesc.convert(self, value) ] 3414762Snate@binkert.org 3424762Snate@binkert.org if isSimObjectSequence(tmp_list): 3437528Ssteve.reinhardt@amd.com return SimObjectVector(tmp_list) 3444762Snate@binkert.org else: 3454762Snate@binkert.org return VectorParamValue(tmp_list) 3464762Snate@binkert.org 34710267SGeoffrey.Blake@arm.com # Produce a human readable example string that describes 34810267SGeoffrey.Blake@arm.com # how to set this vector parameter in the absence of a default 34910267SGeoffrey.Blake@arm.com # value. 35010267SGeoffrey.Blake@arm.com def example_str(self): 35110267SGeoffrey.Blake@arm.com s = super(VectorParamDesc, self).example_str() 35210267SGeoffrey.Blake@arm.com help_str = "[" + s + "," + s + ", ...]" 35310267SGeoffrey.Blake@arm.com return help_str 35410267SGeoffrey.Blake@arm.com 35510267SGeoffrey.Blake@arm.com # Produce a human readable representation of the value of this vector param. 35610267SGeoffrey.Blake@arm.com def pretty_print(self, value): 35710267SGeoffrey.Blake@arm.com if isinstance(value, (list, tuple)): 35810267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ] 35910267SGeoffrey.Blake@arm.com elif isinstance(value, str): 36010267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ] 36110267SGeoffrey.Blake@arm.com else: 36210267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, value) ] 36310267SGeoffrey.Blake@arm.com 36410267SGeoffrey.Blake@arm.com return tmp_list 36510267SGeoffrey.Blake@arm.com 36610267SGeoffrey.Blake@arm.com # This is a helper function for the new config system 36710267SGeoffrey.Blake@arm.com def __call__(self, value): 36810267SGeoffrey.Blake@arm.com if isinstance(value, (list, tuple)): 36910267SGeoffrey.Blake@arm.com # list: coerce each element into new list 37010267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) for v in value ] 37110267SGeoffrey.Blake@arm.com elif isinstance(value, str): 37210267SGeoffrey.Blake@arm.com # If input is a csv string 37310364SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) \ 37410364SGeoffrey.Blake@arm.com for v in value.strip('[').strip(']').split(',') ] 37510267SGeoffrey.Blake@arm.com else: 37610267SGeoffrey.Blake@arm.com # singleton: coerce to a single-element list 37710267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, value) ] 37810267SGeoffrey.Blake@arm.com 37910267SGeoffrey.Blake@arm.com return VectorParamValue(tmp_list) 38010267SGeoffrey.Blake@arm.com 3817673Snate@binkert.org def cxx_predecls(self, code): 3827673Snate@binkert.org code('#include <vector>') 3837673Snate@binkert.org self.ptype.cxx_predecls(code) 3843101Sstever@eecs.umich.edu 38511988Sandreas.sandberg@arm.com def pybind_predecls(self, code): 38611988Sandreas.sandberg@arm.com code('#include <vector>') 38711988Sandreas.sandberg@arm.com self.ptype.pybind_predecls(code) 38811988Sandreas.sandberg@arm.com 3897673Snate@binkert.org def cxx_decl(self, code): 3907673Snate@binkert.org code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};') 3913101Sstever@eecs.umich.edu 3923101Sstever@eecs.umich.educlass ParamFactory(object): 3933101Sstever@eecs.umich.edu def __init__(self, param_desc_class, ptype_str = None): 3943101Sstever@eecs.umich.edu self.param_desc_class = param_desc_class 3953101Sstever@eecs.umich.edu self.ptype_str = ptype_str 3963101Sstever@eecs.umich.edu 3973101Sstever@eecs.umich.edu def __getattr__(self, attr): 3983101Sstever@eecs.umich.edu if self.ptype_str: 3993101Sstever@eecs.umich.edu attr = self.ptype_str + '.' + attr 4003101Sstever@eecs.umich.edu return ParamFactory(self.param_desc_class, attr) 4013101Sstever@eecs.umich.edu 4023101Sstever@eecs.umich.edu # E.g., Param.Int(5, "number of widgets") 4033101Sstever@eecs.umich.edu def __call__(self, *args, **kwargs): 4043101Sstever@eecs.umich.edu ptype = None 4053101Sstever@eecs.umich.edu try: 4065033Smilesck@eecs.umich.edu ptype = allParams[self.ptype_str] 4075033Smilesck@eecs.umich.edu except KeyError: 4083101Sstever@eecs.umich.edu # if name isn't defined yet, assume it's a SimObject, and 4093101Sstever@eecs.umich.edu # try to resolve it later 4103101Sstever@eecs.umich.edu pass 4113101Sstever@eecs.umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 4123101Sstever@eecs.umich.edu 4133101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc) 4143101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc) 4153101Sstever@eecs.umich.edu 4163101Sstever@eecs.umich.edu##################################################################### 4173101Sstever@eecs.umich.edu# 4183101Sstever@eecs.umich.edu# Parameter Types 4193101Sstever@eecs.umich.edu# 4203101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types 4213101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more 4223101Sstever@eecs.umich.edu# flexible to define our own set of types. This gives us more control 4233101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the 4243101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via 4253101Sstever@eecs.umich.edu# the __str__() conversion method). 4263101Sstever@eecs.umich.edu# 4273101Sstever@eecs.umich.edu##################################################################### 4283101Sstever@eecs.umich.edu 4293101Sstever@eecs.umich.edu# String-valued parameter. Just mixin the ParamValue class with the 4303101Sstever@eecs.umich.edu# built-in str class. 4313101Sstever@eecs.umich.educlass String(ParamValue,str): 4323101Sstever@eecs.umich.edu cxx_type = 'std::string' 43310267SGeoffrey.Blake@arm.com cmd_line_settable = True 4347673Snate@binkert.org 4357673Snate@binkert.org @classmethod 4367673Snate@binkert.org def cxx_predecls(self, code): 4377673Snate@binkert.org code('#include <string>') 4387673Snate@binkert.org 43910267SGeoffrey.Blake@arm.com def __call__(self, value): 44010267SGeoffrey.Blake@arm.com self = value 44110267SGeoffrey.Blake@arm.com return value 44210267SGeoffrey.Blake@arm.com 44310458Sandreas.hansson@arm.com @classmethod 44410458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 44510458Sandreas.hansson@arm.com code('%s = %s;' % (dest, src)) 44610458Sandreas.hansson@arm.com code('%s true;' % ret) 44710458Sandreas.hansson@arm.com 4484762Snate@binkert.org def getValue(self): 4494762Snate@binkert.org return self 4503101Sstever@eecs.umich.edu 4513101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math 4523101Sstever@eecs.umich.edu# operations in a type-safe way. e.g., a Latency times an int returns 4533101Sstever@eecs.umich.edu# a new Latency object. 4543101Sstever@eecs.umich.educlass NumericParamValue(ParamValue): 4553101Sstever@eecs.umich.edu def __str__(self): 4563101Sstever@eecs.umich.edu return str(self.value) 4573101Sstever@eecs.umich.edu 4583101Sstever@eecs.umich.edu def __float__(self): 4593101Sstever@eecs.umich.edu return float(self.value) 4603101Sstever@eecs.umich.edu 4613714Sstever@eecs.umich.edu def __long__(self): 4623714Sstever@eecs.umich.edu return long(self.value) 4633714Sstever@eecs.umich.edu 4643714Sstever@eecs.umich.edu def __int__(self): 4653714Sstever@eecs.umich.edu return int(self.value) 4663714Sstever@eecs.umich.edu 4673101Sstever@eecs.umich.edu # hook for bounds checking 4683101Sstever@eecs.umich.edu def _check(self): 4693101Sstever@eecs.umich.edu return 4703101Sstever@eecs.umich.edu 4713101Sstever@eecs.umich.edu def __mul__(self, other): 4723101Sstever@eecs.umich.edu newobj = self.__class__(self) 4733101Sstever@eecs.umich.edu newobj.value *= other 4743101Sstever@eecs.umich.edu newobj._check() 4753101Sstever@eecs.umich.edu return newobj 4763101Sstever@eecs.umich.edu 4773101Sstever@eecs.umich.edu __rmul__ = __mul__ 4783101Sstever@eecs.umich.edu 4793101Sstever@eecs.umich.edu def __div__(self, other): 4803101Sstever@eecs.umich.edu newobj = self.__class__(self) 4813101Sstever@eecs.umich.edu newobj.value /= other 4823101Sstever@eecs.umich.edu newobj._check() 4833101Sstever@eecs.umich.edu return newobj 4843101Sstever@eecs.umich.edu 4853101Sstever@eecs.umich.edu def __sub__(self, other): 4863101Sstever@eecs.umich.edu newobj = self.__class__(self) 4873101Sstever@eecs.umich.edu newobj.value -= other 4883101Sstever@eecs.umich.edu newobj._check() 4893101Sstever@eecs.umich.edu return newobj 4903101Sstever@eecs.umich.edu 49110380SAndrew.Bardsley@arm.com def config_value(self): 49210380SAndrew.Bardsley@arm.com return self.value 49310380SAndrew.Bardsley@arm.com 49410458Sandreas.hansson@arm.com @classmethod 49510458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 49610458Sandreas.hansson@arm.com # Assume that base/str.hh will be included anyway 49710458Sandreas.hansson@arm.com # code('#include "base/str.hh"') 49810458Sandreas.hansson@arm.com pass 49910458Sandreas.hansson@arm.com 50010458Sandreas.hansson@arm.com # The default for parsing PODs from an .ini entry is to extract from an 50110458Sandreas.hansson@arm.com # istringstream and let overloading choose the right type according to 50210458Sandreas.hansson@arm.com # the dest type. 50310458Sandreas.hansson@arm.com @classmethod 50410458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 50510458Sandreas.hansson@arm.com code('%s to_number(%s, %s);' % (ret, src, dest)) 50610458Sandreas.hansson@arm.com 5073101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters. See CheckedInt. 5085033Smilesck@eecs.umich.educlass CheckedIntType(MetaParamValue): 5093101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 5103101Sstever@eecs.umich.edu super(CheckedIntType, cls).__init__(name, bases, dict) 5113101Sstever@eecs.umich.edu 5123101Sstever@eecs.umich.edu # CheckedInt is an abstract base class, so we actually don't 5133101Sstever@eecs.umich.edu # want to do any processing on it... the rest of this code is 5143101Sstever@eecs.umich.edu # just for classes that derive from CheckedInt. 5153101Sstever@eecs.umich.edu if name == 'CheckedInt': 5163101Sstever@eecs.umich.edu return 5173101Sstever@eecs.umich.edu 5183101Sstever@eecs.umich.edu if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 5193101Sstever@eecs.umich.edu if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 5203101Sstever@eecs.umich.edu panic("CheckedInt subclass %s must define either\n" \ 5215822Ssaidi@eecs.umich.edu " 'min' and 'max' or 'size' and 'unsigned'\n", 5225822Ssaidi@eecs.umich.edu name); 5233101Sstever@eecs.umich.edu if cls.unsigned: 5243101Sstever@eecs.umich.edu cls.min = 0 5253101Sstever@eecs.umich.edu cls.max = 2 ** cls.size - 1 5263101Sstever@eecs.umich.edu else: 5273101Sstever@eecs.umich.edu cls.min = -(2 ** (cls.size - 1)) 5283101Sstever@eecs.umich.edu cls.max = (2 ** (cls.size - 1)) - 1 5293101Sstever@eecs.umich.edu 5303101Sstever@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters. This 5313101Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific 5323101Sstever@eecs.umich.edu# bounds. Initialization of the min and max bounds is done in the 5333101Sstever@eecs.umich.edu# metaclass CheckedIntType.__init__. 5343101Sstever@eecs.umich.educlass CheckedInt(NumericParamValue): 5353101Sstever@eecs.umich.edu __metaclass__ = CheckedIntType 53610267SGeoffrey.Blake@arm.com cmd_line_settable = True 5373101Sstever@eecs.umich.edu 5383101Sstever@eecs.umich.edu def _check(self): 5393101Sstever@eecs.umich.edu if not self.min <= self.value <= self.max: 5403101Sstever@eecs.umich.edu raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 5413101Sstever@eecs.umich.edu (self.min, self.value, self.max) 5423101Sstever@eecs.umich.edu 5433101Sstever@eecs.umich.edu def __init__(self, value): 5443101Sstever@eecs.umich.edu if isinstance(value, str): 5453102Sstever@eecs.umich.edu self.value = convert.toInteger(value) 5463714Sstever@eecs.umich.edu elif isinstance(value, (int, long, float, NumericParamValue)): 5473101Sstever@eecs.umich.edu self.value = long(value) 5483714Sstever@eecs.umich.edu else: 5493714Sstever@eecs.umich.edu raise TypeError, "Can't convert object of type %s to CheckedInt" \ 5503714Sstever@eecs.umich.edu % type(value).__name__ 5513101Sstever@eecs.umich.edu self._check() 5523101Sstever@eecs.umich.edu 55310267SGeoffrey.Blake@arm.com def __call__(self, value): 55410267SGeoffrey.Blake@arm.com self.__init__(value) 55510267SGeoffrey.Blake@arm.com return value 55610267SGeoffrey.Blake@arm.com 5577673Snate@binkert.org @classmethod 5587673Snate@binkert.org def cxx_predecls(cls, code): 5597673Snate@binkert.org # most derived types require this, so we just do it here once 5607673Snate@binkert.org code('#include "base/types.hh"') 5617673Snate@binkert.org 5624762Snate@binkert.org def getValue(self): 5634762Snate@binkert.org return long(self.value) 5644762Snate@binkert.org 5653101Sstever@eecs.umich.educlass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 5663101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 5673101Sstever@eecs.umich.edu 5683101Sstever@eecs.umich.educlass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 5693101Sstever@eecs.umich.educlass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 5703101Sstever@eecs.umich.educlass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 5713101Sstever@eecs.umich.educlass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 5723101Sstever@eecs.umich.educlass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 5733101Sstever@eecs.umich.educlass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 5743101Sstever@eecs.umich.educlass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 5753101Sstever@eecs.umich.educlass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 5763101Sstever@eecs.umich.edu 5773101Sstever@eecs.umich.educlass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 5783101Sstever@eecs.umich.educlass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 5793101Sstever@eecs.umich.educlass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 5803101Sstever@eecs.umich.educlass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 5813101Sstever@eecs.umich.edu 5823101Sstever@eecs.umich.educlass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 5833101Sstever@eecs.umich.edu 5849184Sandreas.hansson@arm.comclass Cycles(CheckedInt): 5859184Sandreas.hansson@arm.com cxx_type = 'Cycles' 5869184Sandreas.hansson@arm.com size = 64 5879184Sandreas.hansson@arm.com unsigned = True 5889184Sandreas.hansson@arm.com 5899184Sandreas.hansson@arm.com def getValue(self): 59011802Sandreas.sandberg@arm.com from _m5.core import Cycles 5919184Sandreas.hansson@arm.com return Cycles(self.value) 5929184Sandreas.hansson@arm.com 59310458Sandreas.hansson@arm.com @classmethod 59410458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 59510458Sandreas.hansson@arm.com # Assume that base/str.hh will be included anyway 59610458Sandreas.hansson@arm.com # code('#include "base/str.hh"') 59710458Sandreas.hansson@arm.com pass 59810458Sandreas.hansson@arm.com 59910458Sandreas.hansson@arm.com @classmethod 60010458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 60110458Sandreas.hansson@arm.com code('uint64_t _temp;') 60210458Sandreas.hansson@arm.com code('bool _ret = to_number(%s, _temp);' % src) 60310458Sandreas.hansson@arm.com code('if (_ret)') 60410458Sandreas.hansson@arm.com code(' %s = Cycles(_temp);' % dest) 60510458Sandreas.hansson@arm.com code('%s _ret;' % ret) 60610458Sandreas.hansson@arm.com 6073101Sstever@eecs.umich.educlass Float(ParamValue, float): 6084446Sbinkertn@umich.edu cxx_type = 'double' 60910668SGeoffrey.Blake@arm.com cmd_line_settable = True 6103101Sstever@eecs.umich.edu 6115468Snate@binkert.org def __init__(self, value): 61210267SGeoffrey.Blake@arm.com if isinstance(value, (int, long, float, NumericParamValue, Float, str)): 6135468Snate@binkert.org self.value = float(value) 6145468Snate@binkert.org else: 6155468Snate@binkert.org raise TypeError, "Can't convert object of type %s to Float" \ 6165468Snate@binkert.org % type(value).__name__ 6175468Snate@binkert.org 61810267SGeoffrey.Blake@arm.com def __call__(self, value): 61910267SGeoffrey.Blake@arm.com self.__init__(value) 62010267SGeoffrey.Blake@arm.com return value 62110267SGeoffrey.Blake@arm.com 6224762Snate@binkert.org def getValue(self): 6234762Snate@binkert.org return float(self.value) 6244762Snate@binkert.org 62510380SAndrew.Bardsley@arm.com def config_value(self): 62610380SAndrew.Bardsley@arm.com return self 62710380SAndrew.Bardsley@arm.com 62810458Sandreas.hansson@arm.com @classmethod 62910458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 63010458Sandreas.hansson@arm.com code('#include <sstream>') 63110458Sandreas.hansson@arm.com 63210458Sandreas.hansson@arm.com @classmethod 63310458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 63410458Sandreas.hansson@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 63510458Sandreas.hansson@arm.com 6363101Sstever@eecs.umich.educlass MemorySize(CheckedInt): 6373101Sstever@eecs.umich.edu cxx_type = 'uint64_t' 63810267SGeoffrey.Blake@arm.com ex_str = '512MB' 6393101Sstever@eecs.umich.edu size = 64 6403101Sstever@eecs.umich.edu unsigned = True 6413101Sstever@eecs.umich.edu def __init__(self, value): 6423101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 6433101Sstever@eecs.umich.edu self.value = value.value 6443101Sstever@eecs.umich.edu else: 6453102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 6463101Sstever@eecs.umich.edu self._check() 6473101Sstever@eecs.umich.edu 6483101Sstever@eecs.umich.educlass MemorySize32(CheckedInt): 6494168Sbinkertn@umich.edu cxx_type = 'uint32_t' 65010267SGeoffrey.Blake@arm.com ex_str = '512MB' 6513101Sstever@eecs.umich.edu size = 32 6523101Sstever@eecs.umich.edu unsigned = True 6533101Sstever@eecs.umich.edu def __init__(self, value): 6543101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 6553101Sstever@eecs.umich.edu self.value = value.value 6563101Sstever@eecs.umich.edu else: 6573102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 6583101Sstever@eecs.umich.edu self._check() 6593101Sstever@eecs.umich.edu 6603101Sstever@eecs.umich.educlass Addr(CheckedInt): 6613101Sstever@eecs.umich.edu cxx_type = 'Addr' 6623101Sstever@eecs.umich.edu size = 64 6633101Sstever@eecs.umich.edu unsigned = True 6643101Sstever@eecs.umich.edu def __init__(self, value): 6653101Sstever@eecs.umich.edu if isinstance(value, Addr): 6663101Sstever@eecs.umich.edu self.value = value.value 6673101Sstever@eecs.umich.edu else: 6683101Sstever@eecs.umich.edu try: 66910317Smitch.hayenga@arm.com # Often addresses are referred to with sizes. Ex: A device 67010317Smitch.hayenga@arm.com # base address is at "512MB". Use toMemorySize() to convert 67110317Smitch.hayenga@arm.com # these into addresses. If the address is not specified with a 67210317Smitch.hayenga@arm.com # "size", an exception will occur and numeric translation will 67310317Smitch.hayenga@arm.com # proceed below. 6743102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 67510317Smitch.hayenga@arm.com except (TypeError, ValueError): 67610317Smitch.hayenga@arm.com # Convert number to string and use long() to do automatic 67710317Smitch.hayenga@arm.com # base conversion (requires base=0 for auto-conversion) 67810317Smitch.hayenga@arm.com self.value = long(str(value), base=0) 67910317Smitch.hayenga@arm.com 6803101Sstever@eecs.umich.edu self._check() 6813584Ssaidi@eecs.umich.edu def __add__(self, other): 6823584Ssaidi@eecs.umich.edu if isinstance(other, Addr): 6833584Ssaidi@eecs.umich.edu return self.value + other.value 6843584Ssaidi@eecs.umich.edu else: 6853584Ssaidi@eecs.umich.edu return self.value + other 68610267SGeoffrey.Blake@arm.com def pretty_print(self, value): 68710267SGeoffrey.Blake@arm.com try: 68810267SGeoffrey.Blake@arm.com val = convert.toMemorySize(value) 68910267SGeoffrey.Blake@arm.com except TypeError: 69010267SGeoffrey.Blake@arm.com val = long(value) 69110267SGeoffrey.Blake@arm.com return "0x%x" % long(val) 6923101Sstever@eecs.umich.edu 6939232Sandreas.hansson@arm.comclass AddrRange(ParamValue): 6949235Sandreas.hansson@arm.com cxx_type = 'AddrRange' 6953101Sstever@eecs.umich.edu 6963101Sstever@eecs.umich.edu def __init__(self, *args, **kwargs): 69710676Sandreas.hansson@arm.com # Disable interleaving and hashing by default 6989411Sandreas.hansson@arm.com self.intlvHighBit = 0 69910676Sandreas.hansson@arm.com self.xorHighBit = 0 7009411Sandreas.hansson@arm.com self.intlvBits = 0 7019411Sandreas.hansson@arm.com self.intlvMatch = 0 7029411Sandreas.hansson@arm.com 7033101Sstever@eecs.umich.edu def handle_kwargs(self, kwargs): 7049411Sandreas.hansson@arm.com # An address range needs to have an upper limit, specified 7059411Sandreas.hansson@arm.com # either explicitly with an end, or as an offset using the 7069411Sandreas.hansson@arm.com # size keyword. 7073101Sstever@eecs.umich.edu if 'end' in kwargs: 7089232Sandreas.hansson@arm.com self.end = Addr(kwargs.pop('end')) 7093101Sstever@eecs.umich.edu elif 'size' in kwargs: 7109232Sandreas.hansson@arm.com self.end = self.start + Addr(kwargs.pop('size')) - 1 7113101Sstever@eecs.umich.edu else: 7123101Sstever@eecs.umich.edu raise TypeError, "Either end or size must be specified" 7133101Sstever@eecs.umich.edu 7149411Sandreas.hansson@arm.com # Now on to the optional bit 7159411Sandreas.hansson@arm.com if 'intlvHighBit' in kwargs: 7169411Sandreas.hansson@arm.com self.intlvHighBit = int(kwargs.pop('intlvHighBit')) 71710676Sandreas.hansson@arm.com if 'xorHighBit' in kwargs: 71810676Sandreas.hansson@arm.com self.xorHighBit = int(kwargs.pop('xorHighBit')) 7199411Sandreas.hansson@arm.com if 'intlvBits' in kwargs: 7209411Sandreas.hansson@arm.com self.intlvBits = int(kwargs.pop('intlvBits')) 7219411Sandreas.hansson@arm.com if 'intlvMatch' in kwargs: 7229411Sandreas.hansson@arm.com self.intlvMatch = int(kwargs.pop('intlvMatch')) 7239411Sandreas.hansson@arm.com 7243101Sstever@eecs.umich.edu if len(args) == 0: 7259232Sandreas.hansson@arm.com self.start = Addr(kwargs.pop('start')) 7263101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 7273101Sstever@eecs.umich.edu 7283101Sstever@eecs.umich.edu elif len(args) == 1: 7293101Sstever@eecs.umich.edu if kwargs: 7309232Sandreas.hansson@arm.com self.start = Addr(args[0]) 7313101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 7325219Ssaidi@eecs.umich.edu elif isinstance(args[0], (list, tuple)): 7339232Sandreas.hansson@arm.com self.start = Addr(args[0][0]) 7349232Sandreas.hansson@arm.com self.end = Addr(args[0][1]) 7353101Sstever@eecs.umich.edu else: 7369232Sandreas.hansson@arm.com self.start = Addr(0) 7379232Sandreas.hansson@arm.com self.end = Addr(args[0]) - 1 7383101Sstever@eecs.umich.edu 7393101Sstever@eecs.umich.edu elif len(args) == 2: 7409232Sandreas.hansson@arm.com self.start = Addr(args[0]) 7419232Sandreas.hansson@arm.com self.end = Addr(args[1]) 7423101Sstever@eecs.umich.edu else: 7433101Sstever@eecs.umich.edu raise TypeError, "Too many arguments specified" 7443101Sstever@eecs.umich.edu 7453101Sstever@eecs.umich.edu if kwargs: 7469232Sandreas.hansson@arm.com raise TypeError, "Too many keywords: %s" % kwargs.keys() 7473101Sstever@eecs.umich.edu 7483101Sstever@eecs.umich.edu def __str__(self): 74911620SMatthew.Poremba@amd.com return '%s:%s:%s:%s:%s:%s' \ 75011620SMatthew.Poremba@amd.com % (self.start, self.end, self.intlvHighBit, self.xorHighBit,\ 75111620SMatthew.Poremba@amd.com self.intlvBits, self.intlvMatch) 7529232Sandreas.hansson@arm.com 7539232Sandreas.hansson@arm.com def size(self): 7549411Sandreas.hansson@arm.com # Divide the size by the size of the interleaving slice 7559411Sandreas.hansson@arm.com return (long(self.end) - long(self.start) + 1) >> self.intlvBits 7563101Sstever@eecs.umich.edu 7577673Snate@binkert.org @classmethod 7587673Snate@binkert.org def cxx_predecls(cls, code): 7599232Sandreas.hansson@arm.com Addr.cxx_predecls(code) 7609235Sandreas.hansson@arm.com code('#include "base/addr_range.hh"') 7617675Snate@binkert.org 7627675Snate@binkert.org @classmethod 76311988Sandreas.sandberg@arm.com def pybind_predecls(cls, code): 76411988Sandreas.sandberg@arm.com Addr.pybind_predecls(code) 76511988Sandreas.sandberg@arm.com code('#include "base/addr_range.hh"') 76611988Sandreas.sandberg@arm.com 76711988Sandreas.sandberg@arm.com @classmethod 76810458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 76910458Sandreas.hansson@arm.com code('#include <sstream>') 77010458Sandreas.hansson@arm.com 77110458Sandreas.hansson@arm.com @classmethod 77210458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 77311620SMatthew.Poremba@amd.com code('uint64_t _start, _end, _intlvHighBit = 0, _xorHighBit = 0;') 77411620SMatthew.Poremba@amd.com code('uint64_t _intlvBits = 0, _intlvMatch = 0;') 77510458Sandreas.hansson@arm.com code('char _sep;') 77610458Sandreas.hansson@arm.com code('std::istringstream _stream(${src});') 77710458Sandreas.hansson@arm.com code('_stream >> _start;') 77810458Sandreas.hansson@arm.com code('_stream.get(_sep);') 77910458Sandreas.hansson@arm.com code('_stream >> _end;') 78011620SMatthew.Poremba@amd.com code('if (!_stream.fail() && !_stream.eof()) {') 78111620SMatthew.Poremba@amd.com code(' _stream.get(_sep);') 78211620SMatthew.Poremba@amd.com code(' _stream >> _intlvHighBit;') 78311620SMatthew.Poremba@amd.com code(' _stream.get(_sep);') 78411620SMatthew.Poremba@amd.com code(' _stream >> _xorHighBit;') 78511620SMatthew.Poremba@amd.com code(' _stream.get(_sep);') 78611620SMatthew.Poremba@amd.com code(' _stream >> _intlvBits;') 78711620SMatthew.Poremba@amd.com code(' _stream.get(_sep);') 78811620SMatthew.Poremba@amd.com code(' _stream >> _intlvMatch;') 78911620SMatthew.Poremba@amd.com code('}') 79010458Sandreas.hansson@arm.com code('bool _ret = !_stream.fail() &&' 79110458Sandreas.hansson@arm.com '_stream.eof() && _sep == \':\';') 79210458Sandreas.hansson@arm.com code('if (_ret)') 79311620SMatthew.Poremba@amd.com code(' ${dest} = AddrRange(_start, _end, _intlvHighBit, \ 79411620SMatthew.Poremba@amd.com _xorHighBit, _intlvBits, _intlvMatch);') 79510458Sandreas.hansson@arm.com code('${ret} _ret;') 79610458Sandreas.hansson@arm.com 7974762Snate@binkert.org def getValue(self): 79811991Sandreas.sandberg@arm.com # Go from the Python class to the wrapped C++ class 79911802Sandreas.sandberg@arm.com from _m5.range import AddrRange 8004762Snate@binkert.org 8019411Sandreas.hansson@arm.com return AddrRange(long(self.start), long(self.end), 80210676Sandreas.hansson@arm.com int(self.intlvHighBit), int(self.xorHighBit), 80310676Sandreas.hansson@arm.com int(self.intlvBits), int(self.intlvMatch)) 8043101Sstever@eecs.umich.edu 8053101Sstever@eecs.umich.edu# Boolean parameter type. Python doesn't let you subclass bool, since 8063101Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and 8073101Sstever@eecs.umich.edu# False. Thus this is a little more complicated than String. 8083101Sstever@eecs.umich.educlass Bool(ParamValue): 8093101Sstever@eecs.umich.edu cxx_type = 'bool' 81010267SGeoffrey.Blake@arm.com cmd_line_settable = True 81110267SGeoffrey.Blake@arm.com 8123101Sstever@eecs.umich.edu def __init__(self, value): 8133101Sstever@eecs.umich.edu try: 8143102Sstever@eecs.umich.edu self.value = convert.toBool(value) 8153101Sstever@eecs.umich.edu except TypeError: 8163101Sstever@eecs.umich.edu self.value = bool(value) 8173101Sstever@eecs.umich.edu 81810267SGeoffrey.Blake@arm.com def __call__(self, value): 81910267SGeoffrey.Blake@arm.com self.__init__(value) 82010267SGeoffrey.Blake@arm.com return value 82110267SGeoffrey.Blake@arm.com 8224762Snate@binkert.org def getValue(self): 8234762Snate@binkert.org return bool(self.value) 8244762Snate@binkert.org 8253101Sstever@eecs.umich.edu def __str__(self): 8263101Sstever@eecs.umich.edu return str(self.value) 8273101Sstever@eecs.umich.edu 8288934SBrad.Beckmann@amd.com # implement truth value testing for Bool parameters so that these params 8298934SBrad.Beckmann@amd.com # evaluate correctly during the python configuration phase 8308934SBrad.Beckmann@amd.com def __nonzero__(self): 8318934SBrad.Beckmann@amd.com return bool(self.value) 8328934SBrad.Beckmann@amd.com 8333101Sstever@eecs.umich.edu def ini_str(self): 8343101Sstever@eecs.umich.edu if self.value: 8353101Sstever@eecs.umich.edu return 'true' 8363101Sstever@eecs.umich.edu return 'false' 8373101Sstever@eecs.umich.edu 83810380SAndrew.Bardsley@arm.com def config_value(self): 83910380SAndrew.Bardsley@arm.com return self.value 84010380SAndrew.Bardsley@arm.com 84110458Sandreas.hansson@arm.com @classmethod 84210458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 84310458Sandreas.hansson@arm.com # Assume that base/str.hh will be included anyway 84410458Sandreas.hansson@arm.com # code('#include "base/str.hh"') 84510458Sandreas.hansson@arm.com pass 84610458Sandreas.hansson@arm.com 84710458Sandreas.hansson@arm.com @classmethod 84810458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 84910458Sandreas.hansson@arm.com code('%s to_bool(%s, %s);' % (ret, src, dest)) 85010458Sandreas.hansson@arm.com 8513101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1): 8523101Sstever@eecs.umich.edu bytes = map(lambda x: int(x, 16), addr.split(':')) 8533101Sstever@eecs.umich.edu bytes[5] += val 8543101Sstever@eecs.umich.edu for i in (5, 4, 3, 2, 1): 8553101Sstever@eecs.umich.edu val,rem = divmod(bytes[i], 256) 8563101Sstever@eecs.umich.edu bytes[i] = rem 8573101Sstever@eecs.umich.edu if val == 0: 8583101Sstever@eecs.umich.edu break 8593101Sstever@eecs.umich.edu bytes[i - 1] += val 8603101Sstever@eecs.umich.edu assert(bytes[0] <= 255) 8613101Sstever@eecs.umich.edu return ':'.join(map(lambda x: '%02x' % x, bytes)) 8623101Sstever@eecs.umich.edu 8634380Sbinkertn@umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 8644380Sbinkertn@umich.edudef NextEthernetAddr(): 8654380Sbinkertn@umich.edu global _NextEthernetAddr 8663101Sstever@eecs.umich.edu 8674380Sbinkertn@umich.edu value = _NextEthernetAddr 8684380Sbinkertn@umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 8694380Sbinkertn@umich.edu return value 8703101Sstever@eecs.umich.edu 8713101Sstever@eecs.umich.educlass EthernetAddr(ParamValue): 8723101Sstever@eecs.umich.edu cxx_type = 'Net::EthAddr' 87310267SGeoffrey.Blake@arm.com ex_str = "00:90:00:00:00:01" 87410267SGeoffrey.Blake@arm.com cmd_line_settable = True 8757673Snate@binkert.org 8767673Snate@binkert.org @classmethod 8777673Snate@binkert.org def cxx_predecls(cls, code): 8787673Snate@binkert.org code('#include "base/inet.hh"') 8797673Snate@binkert.org 8803101Sstever@eecs.umich.edu def __init__(self, value): 8813101Sstever@eecs.umich.edu if value == NextEthernetAddr: 8823101Sstever@eecs.umich.edu self.value = value 8833101Sstever@eecs.umich.edu return 8843101Sstever@eecs.umich.edu 8853101Sstever@eecs.umich.edu if not isinstance(value, str): 8863101Sstever@eecs.umich.edu raise TypeError, "expected an ethernet address and didn't get one" 8873101Sstever@eecs.umich.edu 8883101Sstever@eecs.umich.edu bytes = value.split(':') 8893101Sstever@eecs.umich.edu if len(bytes) != 6: 8903101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 8913101Sstever@eecs.umich.edu 8923101Sstever@eecs.umich.edu for byte in bytes: 8939941SGeoffrey.Blake@arm.com if not 0 <= int(byte, base=16) <= 0xff: 8943101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 8953101Sstever@eecs.umich.edu 8963101Sstever@eecs.umich.edu self.value = value 8973101Sstever@eecs.umich.edu 89810267SGeoffrey.Blake@arm.com def __call__(self, value): 89910267SGeoffrey.Blake@arm.com self.__init__(value) 90010267SGeoffrey.Blake@arm.com return value 90110267SGeoffrey.Blake@arm.com 9023101Sstever@eecs.umich.edu def unproxy(self, base): 9033101Sstever@eecs.umich.edu if self.value == NextEthernetAddr: 9044380Sbinkertn@umich.edu return EthernetAddr(self.value()) 9053101Sstever@eecs.umich.edu return self 9063101Sstever@eecs.umich.edu 9074762Snate@binkert.org def getValue(self): 90811988Sandreas.sandberg@arm.com from _m5.net import EthAddr 9094762Snate@binkert.org return EthAddr(self.value) 9104762Snate@binkert.org 91111228SAndrew.Bardsley@arm.com def __str__(self): 91211228SAndrew.Bardsley@arm.com return self.value 91311228SAndrew.Bardsley@arm.com 9144380Sbinkertn@umich.edu def ini_str(self): 9154380Sbinkertn@umich.edu return self.value 9163101Sstever@eecs.umich.edu 91710458Sandreas.hansson@arm.com @classmethod 91810458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 91910458Sandreas.hansson@arm.com code('%s = Net::EthAddr(%s);' % (dest, src)) 92010458Sandreas.hansson@arm.com code('%s true;' % ret) 92110458Sandreas.hansson@arm.com 9227777Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of 9237777Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP. 9247777Sgblack@eecs.umich.educlass IpAddress(ParamValue): 9257777Sgblack@eecs.umich.edu cxx_type = 'Net::IpAddress' 92610267SGeoffrey.Blake@arm.com ex_str = "127.0.0.1" 92710267SGeoffrey.Blake@arm.com cmd_line_settable = True 9287777Sgblack@eecs.umich.edu 9297777Sgblack@eecs.umich.edu @classmethod 9307777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 9317777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 9327777Sgblack@eecs.umich.edu 9337777Sgblack@eecs.umich.edu def __init__(self, value): 9347777Sgblack@eecs.umich.edu if isinstance(value, IpAddress): 9357777Sgblack@eecs.umich.edu self.ip = value.ip 9367777Sgblack@eecs.umich.edu else: 9377777Sgblack@eecs.umich.edu try: 9387777Sgblack@eecs.umich.edu self.ip = convert.toIpAddress(value) 9397777Sgblack@eecs.umich.edu except TypeError: 9407777Sgblack@eecs.umich.edu self.ip = long(value) 9417777Sgblack@eecs.umich.edu self.verifyIp() 9427777Sgblack@eecs.umich.edu 94310267SGeoffrey.Blake@arm.com def __call__(self, value): 94410267SGeoffrey.Blake@arm.com self.__init__(value) 94510267SGeoffrey.Blake@arm.com return value 94610267SGeoffrey.Blake@arm.com 9478579Ssteve.reinhardt@amd.com def __str__(self): 9488579Ssteve.reinhardt@amd.com tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)] 9498579Ssteve.reinhardt@amd.com return '%d.%d.%d.%d' % tuple(tup) 9508579Ssteve.reinhardt@amd.com 9518579Ssteve.reinhardt@amd.com def __eq__(self, other): 9528579Ssteve.reinhardt@amd.com if isinstance(other, IpAddress): 9538579Ssteve.reinhardt@amd.com return self.ip == other.ip 9548579Ssteve.reinhardt@amd.com elif isinstance(other, str): 9558579Ssteve.reinhardt@amd.com try: 9568579Ssteve.reinhardt@amd.com return self.ip == convert.toIpAddress(other) 9578579Ssteve.reinhardt@amd.com except: 9588579Ssteve.reinhardt@amd.com return False 9598579Ssteve.reinhardt@amd.com else: 9608579Ssteve.reinhardt@amd.com return self.ip == other 9618579Ssteve.reinhardt@amd.com 9628579Ssteve.reinhardt@amd.com def __ne__(self, other): 9638579Ssteve.reinhardt@amd.com return not (self == other) 9648579Ssteve.reinhardt@amd.com 9657777Sgblack@eecs.umich.edu def verifyIp(self): 9667777Sgblack@eecs.umich.edu if self.ip < 0 or self.ip >= (1 << 32): 9677798Sgblack@eecs.umich.edu raise TypeError, "invalid ip address %#08x" % self.ip 9687777Sgblack@eecs.umich.edu 9697777Sgblack@eecs.umich.edu def getValue(self): 97011988Sandreas.sandberg@arm.com from _m5.net import IpAddress 9717777Sgblack@eecs.umich.edu return IpAddress(self.ip) 9727777Sgblack@eecs.umich.edu 9737777Sgblack@eecs.umich.edu# When initializing an IpNetmask, pass in an existing IpNetmask, a string of 9747777Sgblack@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 9757777Sgblack@eecs.umich.edu# positional or keyword arguments. 9767777Sgblack@eecs.umich.educlass IpNetmask(IpAddress): 9777777Sgblack@eecs.umich.edu cxx_type = 'Net::IpNetmask' 97810267SGeoffrey.Blake@arm.com ex_str = "127.0.0.0/24" 97910267SGeoffrey.Blake@arm.com cmd_line_settable = True 9807777Sgblack@eecs.umich.edu 9817777Sgblack@eecs.umich.edu @classmethod 9827777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 9837777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 9847777Sgblack@eecs.umich.edu 9857777Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 9867777Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 9877777Sgblack@eecs.umich.edu if key in kwargs: 9887777Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 9897777Sgblack@eecs.umich.edu elif elseVal: 9907777Sgblack@eecs.umich.edu setattr(self, key, elseVal) 9917777Sgblack@eecs.umich.edu else: 9927777Sgblack@eecs.umich.edu raise TypeError, "No value set for %s" % key 9937777Sgblack@eecs.umich.edu 9947777Sgblack@eecs.umich.edu if len(args) == 0: 9957777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip') 9967777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask') 9977777Sgblack@eecs.umich.edu 9987777Sgblack@eecs.umich.edu elif len(args) == 1: 9997777Sgblack@eecs.umich.edu if kwargs: 10007777Sgblack@eecs.umich.edu if not 'ip' in kwargs and not 'netmask' in kwargs: 10017777Sgblack@eecs.umich.edu raise TypeError, "Invalid arguments" 10027777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 10037777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask', args[0]) 10047777Sgblack@eecs.umich.edu elif isinstance(args[0], IpNetmask): 10057777Sgblack@eecs.umich.edu self.ip = args[0].ip 10067777Sgblack@eecs.umich.edu self.netmask = args[0].netmask 10077777Sgblack@eecs.umich.edu else: 10087777Sgblack@eecs.umich.edu (self.ip, self.netmask) = convert.toIpNetmask(args[0]) 10097777Sgblack@eecs.umich.edu 10107777Sgblack@eecs.umich.edu elif len(args) == 2: 10117777Sgblack@eecs.umich.edu self.ip = args[0] 10127777Sgblack@eecs.umich.edu self.netmask = args[1] 10137777Sgblack@eecs.umich.edu else: 10147777Sgblack@eecs.umich.edu raise TypeError, "Too many arguments specified" 10157777Sgblack@eecs.umich.edu 10167777Sgblack@eecs.umich.edu if kwargs: 10177777Sgblack@eecs.umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 10187777Sgblack@eecs.umich.edu 10197777Sgblack@eecs.umich.edu self.verify() 10207777Sgblack@eecs.umich.edu 102110267SGeoffrey.Blake@arm.com def __call__(self, value): 102210267SGeoffrey.Blake@arm.com self.__init__(value) 102310267SGeoffrey.Blake@arm.com return value 102410267SGeoffrey.Blake@arm.com 10258579Ssteve.reinhardt@amd.com def __str__(self): 10268579Ssteve.reinhardt@amd.com return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask) 10278579Ssteve.reinhardt@amd.com 10288579Ssteve.reinhardt@amd.com def __eq__(self, other): 10298579Ssteve.reinhardt@amd.com if isinstance(other, IpNetmask): 10308579Ssteve.reinhardt@amd.com return self.ip == other.ip and self.netmask == other.netmask 10318579Ssteve.reinhardt@amd.com elif isinstance(other, str): 10328579Ssteve.reinhardt@amd.com try: 10338579Ssteve.reinhardt@amd.com return (self.ip, self.netmask) == convert.toIpNetmask(other) 10348579Ssteve.reinhardt@amd.com except: 10358579Ssteve.reinhardt@amd.com return False 10368579Ssteve.reinhardt@amd.com else: 10378579Ssteve.reinhardt@amd.com return False 10388579Ssteve.reinhardt@amd.com 10397777Sgblack@eecs.umich.edu def verify(self): 10407777Sgblack@eecs.umich.edu self.verifyIp() 10417777Sgblack@eecs.umich.edu if self.netmask < 0 or self.netmask > 32: 10427777Sgblack@eecs.umich.edu raise TypeError, "invalid netmask %d" % netmask 10437777Sgblack@eecs.umich.edu 10447777Sgblack@eecs.umich.edu def getValue(self): 104511988Sandreas.sandberg@arm.com from _m5.net import IpNetmask 10467777Sgblack@eecs.umich.edu return IpNetmask(self.ip, self.netmask) 10477777Sgblack@eecs.umich.edu 10487777Sgblack@eecs.umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of 10497777Sgblack@eecs.umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments. 10507777Sgblack@eecs.umich.educlass IpWithPort(IpAddress): 10517777Sgblack@eecs.umich.edu cxx_type = 'Net::IpWithPort' 105210267SGeoffrey.Blake@arm.com ex_str = "127.0.0.1:80" 105310267SGeoffrey.Blake@arm.com cmd_line_settable = True 10547777Sgblack@eecs.umich.edu 10557777Sgblack@eecs.umich.edu @classmethod 10567777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 10577777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 10587777Sgblack@eecs.umich.edu 10597777Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 10607777Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 10617777Sgblack@eecs.umich.edu if key in kwargs: 10627777Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 10637777Sgblack@eecs.umich.edu elif elseVal: 10647777Sgblack@eecs.umich.edu setattr(self, key, elseVal) 10657777Sgblack@eecs.umich.edu else: 10667777Sgblack@eecs.umich.edu raise TypeError, "No value set for %s" % key 10677777Sgblack@eecs.umich.edu 10687777Sgblack@eecs.umich.edu if len(args) == 0: 10697777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip') 10707777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'port') 10717777Sgblack@eecs.umich.edu 10727777Sgblack@eecs.umich.edu elif len(args) == 1: 10737777Sgblack@eecs.umich.edu if kwargs: 10747777Sgblack@eecs.umich.edu if not 'ip' in kwargs and not 'port' in kwargs: 10757777Sgblack@eecs.umich.edu raise TypeError, "Invalid arguments" 10767777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 10777777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'port', args[0]) 10787777Sgblack@eecs.umich.edu elif isinstance(args[0], IpWithPort): 10797777Sgblack@eecs.umich.edu self.ip = args[0].ip 10807777Sgblack@eecs.umich.edu self.port = args[0].port 10817777Sgblack@eecs.umich.edu else: 10827777Sgblack@eecs.umich.edu (self.ip, self.port) = convert.toIpWithPort(args[0]) 10837777Sgblack@eecs.umich.edu 10847777Sgblack@eecs.umich.edu elif len(args) == 2: 10857777Sgblack@eecs.umich.edu self.ip = args[0] 10867777Sgblack@eecs.umich.edu self.port = args[1] 10877777Sgblack@eecs.umich.edu else: 10887777Sgblack@eecs.umich.edu raise TypeError, "Too many arguments specified" 10897777Sgblack@eecs.umich.edu 10907777Sgblack@eecs.umich.edu if kwargs: 10917777Sgblack@eecs.umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 10927777Sgblack@eecs.umich.edu 10937777Sgblack@eecs.umich.edu self.verify() 10947777Sgblack@eecs.umich.edu 109510267SGeoffrey.Blake@arm.com def __call__(self, value): 109610267SGeoffrey.Blake@arm.com self.__init__(value) 109710267SGeoffrey.Blake@arm.com return value 109810267SGeoffrey.Blake@arm.com 10998579Ssteve.reinhardt@amd.com def __str__(self): 11008579Ssteve.reinhardt@amd.com return "%s:%d" % (super(IpWithPort, self).__str__(), self.port) 11018579Ssteve.reinhardt@amd.com 11028579Ssteve.reinhardt@amd.com def __eq__(self, other): 11038579Ssteve.reinhardt@amd.com if isinstance(other, IpWithPort): 11048579Ssteve.reinhardt@amd.com return self.ip == other.ip and self.port == other.port 11058579Ssteve.reinhardt@amd.com elif isinstance(other, str): 11068579Ssteve.reinhardt@amd.com try: 11078579Ssteve.reinhardt@amd.com return (self.ip, self.port) == convert.toIpWithPort(other) 11088579Ssteve.reinhardt@amd.com except: 11098579Ssteve.reinhardt@amd.com return False 11108579Ssteve.reinhardt@amd.com else: 11118579Ssteve.reinhardt@amd.com return False 11128579Ssteve.reinhardt@amd.com 11137777Sgblack@eecs.umich.edu def verify(self): 11147777Sgblack@eecs.umich.edu self.verifyIp() 11157777Sgblack@eecs.umich.edu if self.port < 0 or self.port > 0xffff: 11167777Sgblack@eecs.umich.edu raise TypeError, "invalid port %d" % self.port 11177777Sgblack@eecs.umich.edu 11187777Sgblack@eecs.umich.edu def getValue(self): 111911988Sandreas.sandberg@arm.com from _m5.net import IpWithPort 11207777Sgblack@eecs.umich.edu return IpWithPort(self.ip, self.port) 11217777Sgblack@eecs.umich.edu 11223932Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 112310380SAndrew.Bardsley@arm.com "%a %b %d %H:%M:%S %Y", 11243932Sbinkertn@umich.edu "%Y/%m/%d %H:%M:%S", 11253932Sbinkertn@umich.edu "%Y/%m/%d %H:%M", 11263932Sbinkertn@umich.edu "%Y/%m/%d", 11273932Sbinkertn@umich.edu "%m/%d/%Y %H:%M:%S", 11283932Sbinkertn@umich.edu "%m/%d/%Y %H:%M", 11293932Sbinkertn@umich.edu "%m/%d/%Y", 11303932Sbinkertn@umich.edu "%m/%d/%y %H:%M:%S", 11313932Sbinkertn@umich.edu "%m/%d/%y %H:%M", 11323932Sbinkertn@umich.edu "%m/%d/%y"] 11333932Sbinkertn@umich.edu 11343932Sbinkertn@umich.edu 11353885Sbinkertn@umich.edudef parse_time(value): 11363932Sbinkertn@umich.edu from time import gmtime, strptime, struct_time, time 11373932Sbinkertn@umich.edu from datetime import datetime, date 11383885Sbinkertn@umich.edu 11393932Sbinkertn@umich.edu if isinstance(value, struct_time): 11403932Sbinkertn@umich.edu return value 11413932Sbinkertn@umich.edu 11423932Sbinkertn@umich.edu if isinstance(value, (int, long)): 11433932Sbinkertn@umich.edu return gmtime(value) 11443932Sbinkertn@umich.edu 11453932Sbinkertn@umich.edu if isinstance(value, (datetime, date)): 11463932Sbinkertn@umich.edu return value.timetuple() 11473932Sbinkertn@umich.edu 11483932Sbinkertn@umich.edu if isinstance(value, str): 11493932Sbinkertn@umich.edu if value in ('Now', 'Today'): 11503932Sbinkertn@umich.edu return time.gmtime(time.time()) 11513932Sbinkertn@umich.edu 11523932Sbinkertn@umich.edu for format in time_formats: 11533932Sbinkertn@umich.edu try: 11543932Sbinkertn@umich.edu return strptime(value, format) 11553932Sbinkertn@umich.edu except ValueError: 11563932Sbinkertn@umich.edu pass 11573885Sbinkertn@umich.edu 11583885Sbinkertn@umich.edu raise ValueError, "Could not parse '%s' as a time" % value 11593885Sbinkertn@umich.edu 11603885Sbinkertn@umich.educlass Time(ParamValue): 11614762Snate@binkert.org cxx_type = 'tm' 11627673Snate@binkert.org 11637673Snate@binkert.org @classmethod 11647673Snate@binkert.org def cxx_predecls(cls, code): 11657673Snate@binkert.org code('#include <time.h>') 11667673Snate@binkert.org 11673885Sbinkertn@umich.edu def __init__(self, value): 11683932Sbinkertn@umich.edu self.value = parse_time(value) 11693885Sbinkertn@umich.edu 117010267SGeoffrey.Blake@arm.com def __call__(self, value): 117110267SGeoffrey.Blake@arm.com self.__init__(value) 117210267SGeoffrey.Blake@arm.com return value 117310267SGeoffrey.Blake@arm.com 11744762Snate@binkert.org def getValue(self): 117511988Sandreas.sandberg@arm.com from _m5.core import tm 117611988Sandreas.sandberg@arm.com import calendar 11774762Snate@binkert.org 117811988Sandreas.sandberg@arm.com return tm.gmtime(calendar.timegm(self.value)) 11794762Snate@binkert.org 11803885Sbinkertn@umich.edu def __str__(self): 11814762Snate@binkert.org return time.asctime(self.value) 11823885Sbinkertn@umich.edu 11833885Sbinkertn@umich.edu def ini_str(self): 11843932Sbinkertn@umich.edu return str(self) 11853885Sbinkertn@umich.edu 11868664SAli.Saidi@ARM.com def get_config_as_dict(self): 118710380SAndrew.Bardsley@arm.com assert false 11888664SAli.Saidi@ARM.com return str(self) 11898664SAli.Saidi@ARM.com 119010458Sandreas.hansson@arm.com @classmethod 119110458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 119210458Sandreas.hansson@arm.com code('#include <time.h>') 119310458Sandreas.hansson@arm.com 119410458Sandreas.hansson@arm.com @classmethod 119510458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 119610458Sandreas.hansson@arm.com code('char *_parse_ret = strptime((${src}).c_str(),') 119710458Sandreas.hansson@arm.com code(' "%a %b %d %H:%M:%S %Y", &(${dest}));') 119810458Sandreas.hansson@arm.com code('${ret} _parse_ret && *_parse_ret == \'\\0\';'); 119910458Sandreas.hansson@arm.com 12003101Sstever@eecs.umich.edu# Enumerated types are a little more complex. The user specifies the 12013101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of 12023101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so). (In the 12033101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index 12043101Sstever@eecs.umich.edu# or the corresponding dictionary value. For now, since we only check 12053101Sstever@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file, 12063101Sstever@eecs.umich.edu# there's not much point in using the dictionary.) 12073101Sstever@eecs.umich.edu 12083101Sstever@eecs.umich.edu# What Enum() must do is generate a new type encapsulating the 12093101Sstever@eecs.umich.edu# provided list/dictionary so that specific values of the parameter 12103101Sstever@eecs.umich.edu# can be instances of that type. We define two hidden internal 12113101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then 12123101Sstever@eecs.umich.edu# derive the new type from the appropriate base class on the fly. 12133101Sstever@eecs.umich.edu 12144762Snate@binkert.orgallEnums = {} 12153101Sstever@eecs.umich.edu# Metaclass for Enum types 12165033Smilesck@eecs.umich.educlass MetaEnum(MetaParamValue): 12174762Snate@binkert.org def __new__(mcls, name, bases, dict): 12184762Snate@binkert.org assert name not in allEnums 12194762Snate@binkert.org 12204762Snate@binkert.org cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 12214762Snate@binkert.org allEnums[name] = cls 12224762Snate@binkert.org return cls 12234762Snate@binkert.org 12243101Sstever@eecs.umich.edu def __init__(cls, name, bases, init_dict): 12253101Sstever@eecs.umich.edu if init_dict.has_key('map'): 12263101Sstever@eecs.umich.edu if not isinstance(cls.map, dict): 12273101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'map' " \ 12283101Sstever@eecs.umich.edu "must be of type dict" 12293101Sstever@eecs.umich.edu # build list of value strings from map 12303101Sstever@eecs.umich.edu cls.vals = cls.map.keys() 12313101Sstever@eecs.umich.edu cls.vals.sort() 12323101Sstever@eecs.umich.edu elif init_dict.has_key('vals'): 12333101Sstever@eecs.umich.edu if not isinstance(cls.vals, list): 12343101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'vals' " \ 12353101Sstever@eecs.umich.edu "must be of type list" 12363101Sstever@eecs.umich.edu # build string->value map from vals sequence 12373101Sstever@eecs.umich.edu cls.map = {} 12383101Sstever@eecs.umich.edu for idx,val in enumerate(cls.vals): 12393101Sstever@eecs.umich.edu cls.map[val] = idx 12403101Sstever@eecs.umich.edu else: 12413101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class must define "\ 12423101Sstever@eecs.umich.edu "attribute 'map' or 'vals'" 12433101Sstever@eecs.umich.edu 12444762Snate@binkert.org cls.cxx_type = 'Enums::%s' % name 12453101Sstever@eecs.umich.edu 12463101Sstever@eecs.umich.edu super(MetaEnum, cls).__init__(name, bases, init_dict) 12473101Sstever@eecs.umich.edu 12483101Sstever@eecs.umich.edu # Generate C++ class declaration for this enum type. 12493101Sstever@eecs.umich.edu # Note that we wrap the enum in a class/struct to act as a namespace, 12503101Sstever@eecs.umich.edu # so that the enum strings can be brief w/o worrying about collisions. 12517673Snate@binkert.org def cxx_decl(cls, code): 125210201SAndrew.Bardsley@arm.com wrapper_name = cls.wrapper_name 125310201SAndrew.Bardsley@arm.com wrapper = 'struct' if cls.wrapper_is_struct else 'namespace' 125410201SAndrew.Bardsley@arm.com name = cls.__name__ if cls.enum_name is None else cls.enum_name 125510201SAndrew.Bardsley@arm.com idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name) 125610201SAndrew.Bardsley@arm.com 12577673Snate@binkert.org code('''\ 125810201SAndrew.Bardsley@arm.com#ifndef $idem_macro 125910201SAndrew.Bardsley@arm.com#define $idem_macro 12607673Snate@binkert.org 126110201SAndrew.Bardsley@arm.com$wrapper $wrapper_name { 12627673Snate@binkert.org enum $name { 12637673Snate@binkert.org''') 12647673Snate@binkert.org code.indent(2) 12654762Snate@binkert.org for val in cls.vals: 12667673Snate@binkert.org code('$val = ${{cls.map[val]}},') 12678902Sandreas.hansson@arm.com code('Num_$name = ${{len(cls.vals)}}') 12687673Snate@binkert.org code.dedent(2) 126910201SAndrew.Bardsley@arm.com code(' };') 12704762Snate@binkert.org 127110201SAndrew.Bardsley@arm.com if cls.wrapper_is_struct: 127210201SAndrew.Bardsley@arm.com code(' static const char *${name}Strings[Num_${name}];') 127310201SAndrew.Bardsley@arm.com code('};') 127410201SAndrew.Bardsley@arm.com else: 127510201SAndrew.Bardsley@arm.com code('extern const char *${name}Strings[Num_${name}];') 127610201SAndrew.Bardsley@arm.com code('}') 127710201SAndrew.Bardsley@arm.com 127810201SAndrew.Bardsley@arm.com code() 127910201SAndrew.Bardsley@arm.com code('#endif // $idem_macro') 12807673Snate@binkert.org 12817673Snate@binkert.org def cxx_def(cls, code): 128210201SAndrew.Bardsley@arm.com wrapper_name = cls.wrapper_name 128310201SAndrew.Bardsley@arm.com file_name = cls.__name__ 128410201SAndrew.Bardsley@arm.com name = cls.__name__ if cls.enum_name is None else cls.enum_name 128510201SAndrew.Bardsley@arm.com 128610201SAndrew.Bardsley@arm.com code('#include "enums/$file_name.hh"') 128710201SAndrew.Bardsley@arm.com if cls.wrapper_is_struct: 128810201SAndrew.Bardsley@arm.com code('const char *${wrapper_name}::${name}Strings' 128910201SAndrew.Bardsley@arm.com '[Num_${name}] =') 129010201SAndrew.Bardsley@arm.com else: 129110201SAndrew.Bardsley@arm.com code('namespace Enums {') 129210201SAndrew.Bardsley@arm.com code.indent(1) 129310201SAndrew.Bardsley@arm.com code(' const char *${name}Strings[Num_${name}] =') 129410201SAndrew.Bardsley@arm.com 129510201SAndrew.Bardsley@arm.com code('{') 129610201SAndrew.Bardsley@arm.com code.indent(1) 12974762Snate@binkert.org for val in cls.vals: 12987673Snate@binkert.org code('"$val",') 129910201SAndrew.Bardsley@arm.com code.dedent(1) 130010201SAndrew.Bardsley@arm.com code('};') 130110201SAndrew.Bardsley@arm.com 130210201SAndrew.Bardsley@arm.com if not cls.wrapper_is_struct: 130310201SAndrew.Bardsley@arm.com code('} // namespace $wrapper_name') 130410201SAndrew.Bardsley@arm.com code.dedent(1) 13053101Sstever@eecs.umich.edu 130611988Sandreas.sandberg@arm.com def pybind_def(cls, code): 130711988Sandreas.sandberg@arm.com name = cls.__name__ 130811988Sandreas.sandberg@arm.com wrapper_name = cls.wrapper_name 130911988Sandreas.sandberg@arm.com enum_name = cls.__name__ if cls.enum_name is None else cls.enum_name 131011988Sandreas.sandberg@arm.com 131111988Sandreas.sandberg@arm.com code('''#include "pybind11/pybind11.h" 131211988Sandreas.sandberg@arm.com#include "pybind11/stl.h" 131311988Sandreas.sandberg@arm.com 131411988Sandreas.sandberg@arm.com#include <sim/init.hh> 131511988Sandreas.sandberg@arm.com 131611988Sandreas.sandberg@arm.comnamespace py = pybind11; 131711988Sandreas.sandberg@arm.com 131811988Sandreas.sandberg@arm.comstatic void 131911988Sandreas.sandberg@arm.commodule_init(py::module &m_internal) 132011988Sandreas.sandberg@arm.com{ 132111988Sandreas.sandberg@arm.com py::module m = m_internal.def_submodule("enum_${name}"); 132211988Sandreas.sandberg@arm.com 132311988Sandreas.sandberg@arm.com py::enum_<${wrapper_name}::${enum_name}>(m, "enum_${name}") 132411988Sandreas.sandberg@arm.com''') 132511988Sandreas.sandberg@arm.com 132611988Sandreas.sandberg@arm.com code.indent() 132711988Sandreas.sandberg@arm.com code.indent() 132811988Sandreas.sandberg@arm.com for val in cls.vals: 132911988Sandreas.sandberg@arm.com code('.value("${val}", ${wrapper_name}::${val})') 133011988Sandreas.sandberg@arm.com code('.value("Num_${name}", ${wrapper_name}::Num_${enum_name})') 133111988Sandreas.sandberg@arm.com code('.export_values()') 133211988Sandreas.sandberg@arm.com code(';') 133311988Sandreas.sandberg@arm.com code.dedent() 133411988Sandreas.sandberg@arm.com 133511988Sandreas.sandberg@arm.com code('}') 133611988Sandreas.sandberg@arm.com code.dedent() 133711988Sandreas.sandberg@arm.com code() 133811988Sandreas.sandberg@arm.com code('static EmbeddedPyBind embed_enum("enum_${name}", module_init);') 133911988Sandreas.sandberg@arm.com 13408596Ssteve.reinhardt@amd.com 13413101Sstever@eecs.umich.edu# Base class for enum types. 13423101Sstever@eecs.umich.educlass Enum(ParamValue): 13433101Sstever@eecs.umich.edu __metaclass__ = MetaEnum 13443101Sstever@eecs.umich.edu vals = [] 134510267SGeoffrey.Blake@arm.com cmd_line_settable = True 13463101Sstever@eecs.umich.edu 134710201SAndrew.Bardsley@arm.com # The name of the wrapping namespace or struct 134810201SAndrew.Bardsley@arm.com wrapper_name = 'Enums' 134910201SAndrew.Bardsley@arm.com 135010201SAndrew.Bardsley@arm.com # If true, the enum is wrapped in a struct rather than a namespace 135110201SAndrew.Bardsley@arm.com wrapper_is_struct = False 135210201SAndrew.Bardsley@arm.com 135310201SAndrew.Bardsley@arm.com # If not None, use this as the enum name rather than this class name 135410201SAndrew.Bardsley@arm.com enum_name = None 135510201SAndrew.Bardsley@arm.com 13563101Sstever@eecs.umich.edu def __init__(self, value): 13573101Sstever@eecs.umich.edu if value not in self.map: 13583101Sstever@eecs.umich.edu raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 13593101Sstever@eecs.umich.edu % (value, self.vals) 13603101Sstever@eecs.umich.edu self.value = value 13613101Sstever@eecs.umich.edu 136210267SGeoffrey.Blake@arm.com def __call__(self, value): 136310267SGeoffrey.Blake@arm.com self.__init__(value) 136410267SGeoffrey.Blake@arm.com return value 136510267SGeoffrey.Blake@arm.com 13667675Snate@binkert.org @classmethod 13677675Snate@binkert.org def cxx_predecls(cls, code): 13687675Snate@binkert.org code('#include "enums/$0.hh"', cls.__name__) 13697675Snate@binkert.org 13707675Snate@binkert.org @classmethod 137110458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 137210458Sandreas.hansson@arm.com code('if (false) {') 137310458Sandreas.hansson@arm.com for elem_name in cls.map.iterkeys(): 137410458Sandreas.hansson@arm.com code('} else if (%s == "%s") {' % (src, elem_name)) 137510458Sandreas.hansson@arm.com code.indent() 137610458Sandreas.hansson@arm.com code('%s = Enums::%s;' % (dest, elem_name)) 137710458Sandreas.hansson@arm.com code('%s true;' % ret) 137810458Sandreas.hansson@arm.com code.dedent() 137910458Sandreas.hansson@arm.com code('} else {') 138010458Sandreas.hansson@arm.com code(' %s false;' % ret) 138110458Sandreas.hansson@arm.com code('}') 138210458Sandreas.hansson@arm.com 13834762Snate@binkert.org def getValue(self): 138411988Sandreas.sandberg@arm.com import m5.internal.params 138511988Sandreas.sandberg@arm.com e = getattr(m5.internal.params, "enum_%s" % self.__class__.__name__) 138611988Sandreas.sandberg@arm.com return e(self.map[self.value]) 13874762Snate@binkert.org 13883101Sstever@eecs.umich.edu def __str__(self): 13893101Sstever@eecs.umich.edu return self.value 13903101Sstever@eecs.umich.edu 13913101Sstever@eecs.umich.edu# how big does a rounding error need to be before we warn about it? 13923101Sstever@eecs.umich.edufrequency_tolerance = 0.001 # 0.1% 13933101Sstever@eecs.umich.edu 13944167Sbinkertn@umich.educlass TickParamValue(NumericParamValue): 13953101Sstever@eecs.umich.edu cxx_type = 'Tick' 139610267SGeoffrey.Blake@arm.com ex_str = "1MHz" 139710267SGeoffrey.Blake@arm.com cmd_line_settable = True 13987673Snate@binkert.org 13997673Snate@binkert.org @classmethod 14007673Snate@binkert.org def cxx_predecls(cls, code): 14017673Snate@binkert.org code('#include "base/types.hh"') 14027673Snate@binkert.org 140310267SGeoffrey.Blake@arm.com def __call__(self, value): 140410267SGeoffrey.Blake@arm.com self.__init__(value) 140510267SGeoffrey.Blake@arm.com return value 140610267SGeoffrey.Blake@arm.com 14074762Snate@binkert.org def getValue(self): 14084762Snate@binkert.org return long(self.value) 14094762Snate@binkert.org 141010458Sandreas.hansson@arm.com @classmethod 141110458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 141210458Sandreas.hansson@arm.com code('#include <sstream>') 141310458Sandreas.hansson@arm.com 141410458Sandreas.hansson@arm.com # Ticks are expressed in seconds in JSON files and in plain 141510458Sandreas.hansson@arm.com # Ticks in .ini files. Switch based on a config flag 141610458Sandreas.hansson@arm.com @classmethod 141710458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 141810458Sandreas.hansson@arm.com code('${ret} to_number(${src}, ${dest});') 141910458Sandreas.hansson@arm.com 14204167Sbinkertn@umich.educlass Latency(TickParamValue): 142110267SGeoffrey.Blake@arm.com ex_str = "100ns" 142210267SGeoffrey.Blake@arm.com 14233101Sstever@eecs.umich.edu def __init__(self, value): 14244167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 14254167Sbinkertn@umich.edu self.ticks = value.ticks 14264167Sbinkertn@umich.edu self.value = value.value 14274167Sbinkertn@umich.edu elif isinstance(value, Frequency): 14284167Sbinkertn@umich.edu self.ticks = value.ticks 14294167Sbinkertn@umich.edu self.value = 1.0 / value.value 14304167Sbinkertn@umich.edu elif value.endswith('t'): 14314167Sbinkertn@umich.edu self.ticks = True 14324167Sbinkertn@umich.edu self.value = int(value[:-1]) 14334167Sbinkertn@umich.edu else: 14344167Sbinkertn@umich.edu self.ticks = False 14354167Sbinkertn@umich.edu self.value = convert.toLatency(value) 14363101Sstever@eecs.umich.edu 143710267SGeoffrey.Blake@arm.com def __call__(self, value): 143810267SGeoffrey.Blake@arm.com self.__init__(value) 143910267SGeoffrey.Blake@arm.com return value 144010267SGeoffrey.Blake@arm.com 14413101Sstever@eecs.umich.edu def __getattr__(self, attr): 14423101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 14433101Sstever@eecs.umich.edu return self 14443101Sstever@eecs.umich.edu if attr == 'frequency': 14453101Sstever@eecs.umich.edu return Frequency(self) 14463101Sstever@eecs.umich.edu raise AttributeError, "Latency object has no attribute '%s'" % attr 14473101Sstever@eecs.umich.edu 14484762Snate@binkert.org def getValue(self): 14494762Snate@binkert.org if self.ticks or self.value == 0: 14504762Snate@binkert.org value = self.value 14514762Snate@binkert.org else: 14524762Snate@binkert.org value = ticks.fromSeconds(self.value) 14534762Snate@binkert.org return long(value) 14544762Snate@binkert.org 145510380SAndrew.Bardsley@arm.com def config_value(self): 145610380SAndrew.Bardsley@arm.com return self.getValue() 145710380SAndrew.Bardsley@arm.com 14583101Sstever@eecs.umich.edu # convert latency to ticks 14593101Sstever@eecs.umich.edu def ini_str(self): 14604762Snate@binkert.org return '%d' % self.getValue() 14613101Sstever@eecs.umich.edu 14624167Sbinkertn@umich.educlass Frequency(TickParamValue): 146310267SGeoffrey.Blake@arm.com ex_str = "1GHz" 146410267SGeoffrey.Blake@arm.com 14653101Sstever@eecs.umich.edu def __init__(self, value): 14664167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 14674167Sbinkertn@umich.edu if value.value == 0: 14684167Sbinkertn@umich.edu self.value = 0 14694167Sbinkertn@umich.edu else: 14704167Sbinkertn@umich.edu self.value = 1.0 / value.value 14714167Sbinkertn@umich.edu self.ticks = value.ticks 14724167Sbinkertn@umich.edu elif isinstance(value, Frequency): 14734167Sbinkertn@umich.edu self.value = value.value 14744167Sbinkertn@umich.edu self.ticks = value.ticks 14754167Sbinkertn@umich.edu else: 14764167Sbinkertn@umich.edu self.ticks = False 14774167Sbinkertn@umich.edu self.value = convert.toFrequency(value) 14783101Sstever@eecs.umich.edu 147910267SGeoffrey.Blake@arm.com def __call__(self, value): 148010267SGeoffrey.Blake@arm.com self.__init__(value) 148110267SGeoffrey.Blake@arm.com return value 148210267SGeoffrey.Blake@arm.com 14833101Sstever@eecs.umich.edu def __getattr__(self, attr): 14843101Sstever@eecs.umich.edu if attr == 'frequency': 14853101Sstever@eecs.umich.edu return self 14863101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 14873101Sstever@eecs.umich.edu return Latency(self) 14883101Sstever@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 14893101Sstever@eecs.umich.edu 14904167Sbinkertn@umich.edu # convert latency to ticks 14914762Snate@binkert.org def getValue(self): 14924762Snate@binkert.org if self.ticks or self.value == 0: 14934762Snate@binkert.org value = self.value 14944762Snate@binkert.org else: 14954762Snate@binkert.org value = ticks.fromSeconds(1.0 / self.value) 14964762Snate@binkert.org return long(value) 14974762Snate@binkert.org 149810380SAndrew.Bardsley@arm.com def config_value(self): 149910380SAndrew.Bardsley@arm.com return self.getValue() 150010380SAndrew.Bardsley@arm.com 15013101Sstever@eecs.umich.edu def ini_str(self): 15024762Snate@binkert.org return '%d' % self.getValue() 15033101Sstever@eecs.umich.edu 150410019Sandreas.hansson@arm.com# A generic Frequency and/or Latency value. Value is stored as a 150510019Sandreas.hansson@arm.com# latency, just like Latency and Frequency. 150610019Sandreas.hansson@arm.comclass Clock(TickParamValue): 15073101Sstever@eecs.umich.edu def __init__(self, value): 15084167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 15094167Sbinkertn@umich.edu self.ticks = value.ticks 15104167Sbinkertn@umich.edu self.value = value.value 15114167Sbinkertn@umich.edu elif isinstance(value, Frequency): 15124167Sbinkertn@umich.edu self.ticks = value.ticks 15134167Sbinkertn@umich.edu self.value = 1.0 / value.value 15144167Sbinkertn@umich.edu elif value.endswith('t'): 15154167Sbinkertn@umich.edu self.ticks = True 15164167Sbinkertn@umich.edu self.value = int(value[:-1]) 15174167Sbinkertn@umich.edu else: 15184167Sbinkertn@umich.edu self.ticks = False 15194167Sbinkertn@umich.edu self.value = convert.anyToLatency(value) 15203101Sstever@eecs.umich.edu 152110267SGeoffrey.Blake@arm.com def __call__(self, value): 152210267SGeoffrey.Blake@arm.com self.__init__(value) 152310267SGeoffrey.Blake@arm.com return value 152410267SGeoffrey.Blake@arm.com 152510267SGeoffrey.Blake@arm.com def __str__(self): 152610267SGeoffrey.Blake@arm.com return "%s" % Latency(self) 152710267SGeoffrey.Blake@arm.com 15283101Sstever@eecs.umich.edu def __getattr__(self, attr): 15293101Sstever@eecs.umich.edu if attr == 'frequency': 15303101Sstever@eecs.umich.edu return Frequency(self) 15313101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 15323101Sstever@eecs.umich.edu return Latency(self) 15333101Sstever@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 15343101Sstever@eecs.umich.edu 15354762Snate@binkert.org def getValue(self): 15364762Snate@binkert.org return self.period.getValue() 15374762Snate@binkert.org 153810380SAndrew.Bardsley@arm.com def config_value(self): 153910380SAndrew.Bardsley@arm.com return self.period.config_value() 154010380SAndrew.Bardsley@arm.com 15413101Sstever@eecs.umich.edu def ini_str(self): 15423101Sstever@eecs.umich.edu return self.period.ini_str() 15433101Sstever@eecs.umich.edu 15449827Sakash.bagdia@arm.comclass Voltage(float,ParamValue): 15459827Sakash.bagdia@arm.com cxx_type = 'double' 154610267SGeoffrey.Blake@arm.com ex_str = "1V" 154711498Sakash.bagdia@ARM.com cmd_line_settable = True 154810267SGeoffrey.Blake@arm.com 15499827Sakash.bagdia@arm.com def __new__(cls, value): 15509827Sakash.bagdia@arm.com # convert to voltage 15519827Sakash.bagdia@arm.com val = convert.toVoltage(value) 15529827Sakash.bagdia@arm.com return super(cls, Voltage).__new__(cls, val) 15539827Sakash.bagdia@arm.com 155410267SGeoffrey.Blake@arm.com def __call__(self, value): 155510267SGeoffrey.Blake@arm.com val = convert.toVoltage(value) 155610267SGeoffrey.Blake@arm.com self.__init__(val) 155710267SGeoffrey.Blake@arm.com return value 155810267SGeoffrey.Blake@arm.com 15599827Sakash.bagdia@arm.com def __str__(self): 156010267SGeoffrey.Blake@arm.com return str(self.getValue()) 15619827Sakash.bagdia@arm.com 15629827Sakash.bagdia@arm.com def getValue(self): 15639827Sakash.bagdia@arm.com value = float(self) 15649827Sakash.bagdia@arm.com return value 15659827Sakash.bagdia@arm.com 15669827Sakash.bagdia@arm.com def ini_str(self): 15679827Sakash.bagdia@arm.com return '%f' % self.getValue() 15689827Sakash.bagdia@arm.com 156910458Sandreas.hansson@arm.com @classmethod 157010458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 157110458Sandreas.hansson@arm.com code('#include <sstream>') 157210458Sandreas.hansson@arm.com 157310458Sandreas.hansson@arm.com @classmethod 157410458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 157510458Sandreas.hansson@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 157610458Sandreas.hansson@arm.com 157710427Sandreas.hansson@arm.comclass Current(float, ParamValue): 157810427Sandreas.hansson@arm.com cxx_type = 'double' 157910427Sandreas.hansson@arm.com ex_str = "1mA" 158010427Sandreas.hansson@arm.com cmd_line_settable = False 158110427Sandreas.hansson@arm.com 158210427Sandreas.hansson@arm.com def __new__(cls, value): 158310427Sandreas.hansson@arm.com # convert to current 158410427Sandreas.hansson@arm.com val = convert.toCurrent(value) 158510427Sandreas.hansson@arm.com return super(cls, Current).__new__(cls, val) 158610427Sandreas.hansson@arm.com 158710427Sandreas.hansson@arm.com def __call__(self, value): 158810427Sandreas.hansson@arm.com val = convert.toCurrent(value) 158910427Sandreas.hansson@arm.com self.__init__(val) 159010427Sandreas.hansson@arm.com return value 159110427Sandreas.hansson@arm.com 159210427Sandreas.hansson@arm.com def __str__(self): 159310427Sandreas.hansson@arm.com return str(self.getValue()) 159410427Sandreas.hansson@arm.com 159510427Sandreas.hansson@arm.com def getValue(self): 159610427Sandreas.hansson@arm.com value = float(self) 159710427Sandreas.hansson@arm.com return value 159810427Sandreas.hansson@arm.com 159910427Sandreas.hansson@arm.com def ini_str(self): 160010427Sandreas.hansson@arm.com return '%f' % self.getValue() 160110427Sandreas.hansson@arm.com 160210458Sandreas.hansson@arm.com @classmethod 160310458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 160410458Sandreas.hansson@arm.com code('#include <sstream>') 160510458Sandreas.hansson@arm.com 160610458Sandreas.hansson@arm.com @classmethod 160710458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 160810458Sandreas.hansson@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 160910458Sandreas.hansson@arm.com 16103101Sstever@eecs.umich.educlass NetworkBandwidth(float,ParamValue): 16113101Sstever@eecs.umich.edu cxx_type = 'float' 161210267SGeoffrey.Blake@arm.com ex_str = "1Gbps" 161310267SGeoffrey.Blake@arm.com cmd_line_settable = True 161410267SGeoffrey.Blake@arm.com 16153101Sstever@eecs.umich.edu def __new__(cls, value): 16164167Sbinkertn@umich.edu # convert to bits per second 16174167Sbinkertn@umich.edu val = convert.toNetworkBandwidth(value) 16183101Sstever@eecs.umich.edu return super(cls, NetworkBandwidth).__new__(cls, val) 16193101Sstever@eecs.umich.edu 16203101Sstever@eecs.umich.edu def __str__(self): 16213101Sstever@eecs.umich.edu return str(self.val) 16223101Sstever@eecs.umich.edu 162310267SGeoffrey.Blake@arm.com def __call__(self, value): 162410267SGeoffrey.Blake@arm.com val = convert.toNetworkBandwidth(value) 162510267SGeoffrey.Blake@arm.com self.__init__(val) 162610267SGeoffrey.Blake@arm.com return value 162710267SGeoffrey.Blake@arm.com 16284762Snate@binkert.org def getValue(self): 16294167Sbinkertn@umich.edu # convert to seconds per byte 16304167Sbinkertn@umich.edu value = 8.0 / float(self) 16314167Sbinkertn@umich.edu # convert to ticks per byte 16324762Snate@binkert.org value = ticks.fromSeconds(value) 16334762Snate@binkert.org return float(value) 16344762Snate@binkert.org 16354762Snate@binkert.org def ini_str(self): 16364762Snate@binkert.org return '%f' % self.getValue() 16373101Sstever@eecs.umich.edu 163810380SAndrew.Bardsley@arm.com def config_value(self): 163910380SAndrew.Bardsley@arm.com return '%f' % self.getValue() 164010380SAndrew.Bardsley@arm.com 164110458Sandreas.hansson@arm.com @classmethod 164210458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 164310458Sandreas.hansson@arm.com code('#include <sstream>') 164410458Sandreas.hansson@arm.com 164510458Sandreas.hansson@arm.com @classmethod 164610458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 164710458Sandreas.hansson@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 164810458Sandreas.hansson@arm.com 16493101Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue): 16503101Sstever@eecs.umich.edu cxx_type = 'float' 165110267SGeoffrey.Blake@arm.com ex_str = "1GB/s" 165210267SGeoffrey.Blake@arm.com cmd_line_settable = True 165310267SGeoffrey.Blake@arm.com 16545469Snate@binkert.org def __new__(cls, value): 16557743Sgblack@eecs.umich.edu # convert to bytes per second 16563102Sstever@eecs.umich.edu val = convert.toMemoryBandwidth(value) 16573101Sstever@eecs.umich.edu return super(cls, MemoryBandwidth).__new__(cls, val) 16583101Sstever@eecs.umich.edu 165910267SGeoffrey.Blake@arm.com def __call__(self, value): 166010267SGeoffrey.Blake@arm.com val = convert.toMemoryBandwidth(value) 166110267SGeoffrey.Blake@arm.com self.__init__(val) 166210267SGeoffrey.Blake@arm.com return value 16633101Sstever@eecs.umich.edu 16644762Snate@binkert.org def getValue(self): 16654167Sbinkertn@umich.edu # convert to seconds per byte 16665468Snate@binkert.org value = float(self) 16675468Snate@binkert.org if value: 16685468Snate@binkert.org value = 1.0 / float(self) 16694167Sbinkertn@umich.edu # convert to ticks per byte 16704762Snate@binkert.org value = ticks.fromSeconds(value) 16714762Snate@binkert.org return float(value) 16724762Snate@binkert.org 16734762Snate@binkert.org def ini_str(self): 16744762Snate@binkert.org return '%f' % self.getValue() 16753101Sstever@eecs.umich.edu 167610380SAndrew.Bardsley@arm.com def config_value(self): 167710380SAndrew.Bardsley@arm.com return '%f' % self.getValue() 167810380SAndrew.Bardsley@arm.com 167910458Sandreas.hansson@arm.com @classmethod 168010458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 168110458Sandreas.hansson@arm.com code('#include <sstream>') 168210458Sandreas.hansson@arm.com 168310458Sandreas.hansson@arm.com @classmethod 168410458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 168510458Sandreas.hansson@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 168610458Sandreas.hansson@arm.com 16873101Sstever@eecs.umich.edu# 16883101Sstever@eecs.umich.edu# "Constants"... handy aliases for various values. 16893101Sstever@eecs.umich.edu# 16903101Sstever@eecs.umich.edu 16913102Sstever@eecs.umich.edu# Special class for NULL pointers. Note the special check in 16923102Sstever@eecs.umich.edu# make_param_value() above that lets these be assigned where a 16933102Sstever@eecs.umich.edu# SimObject is required. 16943102Sstever@eecs.umich.edu# only one copy of a particular node 16953102Sstever@eecs.umich.educlass NullSimObject(object): 16963102Sstever@eecs.umich.edu __metaclass__ = Singleton 16973102Sstever@eecs.umich.edu 16983102Sstever@eecs.umich.edu def __call__(cls): 16993102Sstever@eecs.umich.edu return cls 17003102Sstever@eecs.umich.edu 17013102Sstever@eecs.umich.edu def _instantiate(self, parent = None, path = ''): 17023102Sstever@eecs.umich.edu pass 17033102Sstever@eecs.umich.edu 17043102Sstever@eecs.umich.edu def ini_str(self): 17053102Sstever@eecs.umich.edu return 'Null' 17063102Sstever@eecs.umich.edu 17073102Sstever@eecs.umich.edu def unproxy(self, base): 17083102Sstever@eecs.umich.edu return self 17093102Sstever@eecs.umich.edu 17103102Sstever@eecs.umich.edu def set_path(self, parent, name): 17113102Sstever@eecs.umich.edu pass 17124762Snate@binkert.org 171312192Sgabeblack@google.com def set_parent(self, parent, name): 171412192Sgabeblack@google.com pass 171512192Sgabeblack@google.com 171612195Sgabeblack@google.com def clear_parent(self, old_parent): 171712195Sgabeblack@google.com pass 171812195Sgabeblack@google.com 171912196Sgabeblack@google.com def descendants(self): 172012196Sgabeblack@google.com return 172112196Sgabeblack@google.com yield None 172212196Sgabeblack@google.com 17233102Sstever@eecs.umich.edu def __str__(self): 17243102Sstever@eecs.umich.edu return 'Null' 17253102Sstever@eecs.umich.edu 172610380SAndrew.Bardsley@arm.com def config_value(self): 172710380SAndrew.Bardsley@arm.com return None 172810380SAndrew.Bardsley@arm.com 17294762Snate@binkert.org def getValue(self): 17304762Snate@binkert.org return None 17314762Snate@binkert.org 17323102Sstever@eecs.umich.edu# The only instance you'll ever need... 17333102Sstever@eecs.umich.eduNULL = NullSimObject() 17343102Sstever@eecs.umich.edu 17353102Sstever@eecs.umich.edudef isNullPointer(value): 17363102Sstever@eecs.umich.edu return isinstance(value, NullSimObject) 17373102Sstever@eecs.umich.edu 17383101Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound. 17393101Sstever@eecs.umich.eduMaxAddr = Addr.max 17403101Sstever@eecs.umich.eduMaxTick = Tick.max 17413101Sstever@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr) 17423101Sstever@eecs.umich.edu 17433101Sstever@eecs.umich.edu 17443101Sstever@eecs.umich.edu##################################################################### 17453101Sstever@eecs.umich.edu# 17463101Sstever@eecs.umich.edu# Port objects 17473101Sstever@eecs.umich.edu# 17483101Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system. 17493101Sstever@eecs.umich.edu# 17503101Sstever@eecs.umich.edu##################################################################### 17513101Sstever@eecs.umich.edu 17523101Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a 17533101Sstever@eecs.umich.edu# particular SimObject. 17543101Sstever@eecs.umich.educlass PortRef(object): 17558839Sandreas.hansson@arm.com def __init__(self, simobj, name, role): 17563105Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 17573101Sstever@eecs.umich.edu self.simobj = simobj 17583101Sstever@eecs.umich.edu self.name = name 17598839Sandreas.hansson@arm.com self.role = role 17603101Sstever@eecs.umich.edu self.peer = None # not associated with another port yet 17613101Sstever@eecs.umich.edu self.ccConnected = False # C++ port connection done? 17623105Sstever@eecs.umich.edu self.index = -1 # always -1 for non-vector ports 17633101Sstever@eecs.umich.edu 17643103Sstever@eecs.umich.edu def __str__(self): 17653105Sstever@eecs.umich.edu return '%s.%s' % (self.simobj, self.name) 17663103Sstever@eecs.umich.edu 17678840Sandreas.hansson@arm.com def __len__(self): 17688840Sandreas.hansson@arm.com # Return the number of connected ports, i.e. 0 is we have no 17698840Sandreas.hansson@arm.com # peer and 1 if we do. 17708840Sandreas.hansson@arm.com return int(self.peer != None) 17718840Sandreas.hansson@arm.com 17723105Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 17733105Sstever@eecs.umich.edu def ini_str(self): 17743105Sstever@eecs.umich.edu return str(self.peer) 17753105Sstever@eecs.umich.edu 17769017Sandreas.hansson@arm.com # for config.json 17779017Sandreas.hansson@arm.com def get_config_as_dict(self): 17789017Sandreas.hansson@arm.com return {'role' : self.role, 'peer' : str(self.peer)} 17799017Sandreas.hansson@arm.com 17803105Sstever@eecs.umich.edu def __getattr__(self, attr): 17813105Sstever@eecs.umich.edu if attr == 'peerObj': 17823105Sstever@eecs.umich.edu # shorthand for proxies 17833105Sstever@eecs.umich.edu return self.peer.simobj 17843105Sstever@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 17853105Sstever@eecs.umich.edu (self.__class__.__name__, attr) 17863105Sstever@eecs.umich.edu 17873105Sstever@eecs.umich.edu # Full connection is symmetric (both ways). Called via 17883105Sstever@eecs.umich.edu # SimObject.__setattr__ as a result of a port assignment, e.g., 17893109Sstever@eecs.umich.edu # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 17903105Sstever@eecs.umich.edu # e.g., "obj1.portA[3] = obj2.portB". 17913105Sstever@eecs.umich.edu def connect(self, other): 17923105Sstever@eecs.umich.edu if isinstance(other, VectorPortRef): 17933105Sstever@eecs.umich.edu # reference to plain VectorPort is implicit append 17943105Sstever@eecs.umich.edu other = other._get_next() 17953105Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 17969014Sandreas.hansson@arm.com fatal("Port %s is already connected to %s, cannot connect %s\n", 17979014Sandreas.hansson@arm.com self, self.peer, other); 17983101Sstever@eecs.umich.edu self.peer = other 17993109Sstever@eecs.umich.edu if proxy.isproxy(other): 18003109Sstever@eecs.umich.edu other.set_param_desc(PortParamDesc()) 18013109Sstever@eecs.umich.edu elif isinstance(other, PortRef): 18023109Sstever@eecs.umich.edu if other.peer is not self: 18033109Sstever@eecs.umich.edu other.connect(self) 18043109Sstever@eecs.umich.edu else: 18053109Sstever@eecs.umich.edu raise TypeError, \ 18063109Sstever@eecs.umich.edu "assigning non-port reference '%s' to port '%s'" \ 18073109Sstever@eecs.umich.edu % (other, self) 18083101Sstever@eecs.umich.edu 180910355SGeoffrey.Blake@arm.com # Allow a master/slave port pair to be spliced between 181010355SGeoffrey.Blake@arm.com # a port and its connected peer. Useful operation for connecting 181110355SGeoffrey.Blake@arm.com # instrumentation structures into a system when it is necessary 181210355SGeoffrey.Blake@arm.com # to connect the instrumentation after the full system has been 181310355SGeoffrey.Blake@arm.com # constructed. 181410355SGeoffrey.Blake@arm.com def splice(self, new_master_peer, new_slave_peer): 181510355SGeoffrey.Blake@arm.com if self.peer and not proxy.isproxy(self.peer): 181610355SGeoffrey.Blake@arm.com if isinstance(new_master_peer, PortRef) and \ 181710355SGeoffrey.Blake@arm.com isinstance(new_slave_peer, PortRef): 181810355SGeoffrey.Blake@arm.com old_peer = self.peer 181910355SGeoffrey.Blake@arm.com if self.role == 'SLAVE': 182010355SGeoffrey.Blake@arm.com self.peer = new_master_peer 182110355SGeoffrey.Blake@arm.com old_peer.peer = new_slave_peer 182210355SGeoffrey.Blake@arm.com new_master_peer.connect(self) 182310355SGeoffrey.Blake@arm.com new_slave_peer.connect(old_peer) 182410355SGeoffrey.Blake@arm.com elif self.role == 'MASTER': 182510355SGeoffrey.Blake@arm.com self.peer = new_slave_peer 182610355SGeoffrey.Blake@arm.com old_peer.peer = new_master_peer 182710355SGeoffrey.Blake@arm.com new_slave_peer.connect(self) 182810355SGeoffrey.Blake@arm.com new_master_peer.connect(old_peer) 182910355SGeoffrey.Blake@arm.com else: 183010355SGeoffrey.Blake@arm.com panic("Port %s has unknown role, "+\ 183110355SGeoffrey.Blake@arm.com "cannot splice in new peers\n", self) 183210355SGeoffrey.Blake@arm.com else: 183310355SGeoffrey.Blake@arm.com raise TypeError, \ 183410355SGeoffrey.Blake@arm.com "Splicing non-port references '%s','%s' to port '%s'"\ 183510355SGeoffrey.Blake@arm.com % (new_peer, peers_new_peer, self) 183610355SGeoffrey.Blake@arm.com else: 183710355SGeoffrey.Blake@arm.com fatal("Port %s not connected, cannot splice in new peers\n", self) 183810355SGeoffrey.Blake@arm.com 18393105Sstever@eecs.umich.edu def clone(self, simobj, memo): 18403105Sstever@eecs.umich.edu if memo.has_key(self): 18413105Sstever@eecs.umich.edu return memo[self] 18423101Sstever@eecs.umich.edu newRef = copy.copy(self) 18433105Sstever@eecs.umich.edu memo[self] = newRef 18443105Sstever@eecs.umich.edu newRef.simobj = simobj 18453101Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 18463105Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 18473179Sstever@eecs.umich.edu peerObj = self.peer.simobj(_memo=memo) 18483105Sstever@eecs.umich.edu newRef.peer = self.peer.clone(peerObj, memo) 18493105Sstever@eecs.umich.edu assert(not isinstance(newRef.peer, VectorPortRef)) 18503101Sstever@eecs.umich.edu return newRef 18513101Sstever@eecs.umich.edu 18523105Sstever@eecs.umich.edu def unproxy(self, simobj): 18533105Sstever@eecs.umich.edu assert(simobj is self.simobj) 18543105Sstever@eecs.umich.edu if proxy.isproxy(self.peer): 18553105Sstever@eecs.umich.edu try: 18563105Sstever@eecs.umich.edu realPeer = self.peer.unproxy(self.simobj) 18573105Sstever@eecs.umich.edu except: 18583105Sstever@eecs.umich.edu print "Error in unproxying port '%s' of %s" % \ 18593105Sstever@eecs.umich.edu (self.name, self.simobj.path()) 18603105Sstever@eecs.umich.edu raise 18613105Sstever@eecs.umich.edu self.connect(realPeer) 18623105Sstever@eecs.umich.edu 18633101Sstever@eecs.umich.edu # Call C++ to create corresponding port connection between C++ objects 18643101Sstever@eecs.umich.edu def ccConnect(self): 186511802Sandreas.sandberg@arm.com from _m5.pyobject import connectPorts 18664762Snate@binkert.org 18678839Sandreas.hansson@arm.com if self.role == 'SLAVE': 18688839Sandreas.hansson@arm.com # do nothing and let the master take care of it 18698839Sandreas.hansson@arm.com return 18708839Sandreas.hansson@arm.com 18713101Sstever@eecs.umich.edu if self.ccConnected: # already done this 18723101Sstever@eecs.umich.edu return 18733101Sstever@eecs.umich.edu peer = self.peer 18745578SSteve.Reinhardt@amd.com if not self.peer: # nothing to connect to 18755578SSteve.Reinhardt@amd.com return 18768839Sandreas.hansson@arm.com 18778839Sandreas.hansson@arm.com # check that we connect a master to a slave 18788839Sandreas.hansson@arm.com if self.role == peer.role: 18798839Sandreas.hansson@arm.com raise TypeError, \ 18808839Sandreas.hansson@arm.com "cannot connect '%s' and '%s' due to identical role '%s'" \ 18818839Sandreas.hansson@arm.com % (peer, self, self.role) 18828839Sandreas.hansson@arm.com 18837526Ssteve.reinhardt@amd.com try: 18848839Sandreas.hansson@arm.com # self is always the master and peer the slave 18857526Ssteve.reinhardt@amd.com connectPorts(self.simobj.getCCObject(), self.name, self.index, 18867526Ssteve.reinhardt@amd.com peer.simobj.getCCObject(), peer.name, peer.index) 18877526Ssteve.reinhardt@amd.com except: 18887526Ssteve.reinhardt@amd.com print "Error connecting port %s.%s to %s.%s" % \ 18897526Ssteve.reinhardt@amd.com (self.simobj.path(), self.name, 18907526Ssteve.reinhardt@amd.com peer.simobj.path(), peer.name) 18917526Ssteve.reinhardt@amd.com raise 18923101Sstever@eecs.umich.edu self.ccConnected = True 18933101Sstever@eecs.umich.edu peer.ccConnected = True 18943101Sstever@eecs.umich.edu 18953105Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a 18963105Sstever@eecs.umich.edu# PortRef, but has an index. 18973105Sstever@eecs.umich.educlass VectorPortElementRef(PortRef): 18988839Sandreas.hansson@arm.com def __init__(self, simobj, name, role, index): 18998839Sandreas.hansson@arm.com PortRef.__init__(self, simobj, name, role) 19003105Sstever@eecs.umich.edu self.index = index 19013105Sstever@eecs.umich.edu 19023105Sstever@eecs.umich.edu def __str__(self): 19033105Sstever@eecs.umich.edu return '%s.%s[%d]' % (self.simobj, self.name, self.index) 19043105Sstever@eecs.umich.edu 19053105Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element). 19063105Sstever@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances. 19073105Sstever@eecs.umich.educlass VectorPortRef(object): 19088839Sandreas.hansson@arm.com def __init__(self, simobj, name, role): 19093105Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 19103105Sstever@eecs.umich.edu self.simobj = simobj 19113105Sstever@eecs.umich.edu self.name = name 19128839Sandreas.hansson@arm.com self.role = role 19133105Sstever@eecs.umich.edu self.elements = [] 19143105Sstever@eecs.umich.edu 19153109Sstever@eecs.umich.edu def __str__(self): 19163109Sstever@eecs.umich.edu return '%s.%s[:]' % (self.simobj, self.name) 19173109Sstever@eecs.umich.edu 19188840Sandreas.hansson@arm.com def __len__(self): 19198840Sandreas.hansson@arm.com # Return the number of connected peers, corresponding the the 19208840Sandreas.hansson@arm.com # length of the elements. 19218840Sandreas.hansson@arm.com return len(self.elements) 19228840Sandreas.hansson@arm.com 19233105Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 19243105Sstever@eecs.umich.edu def ini_str(self): 19253105Sstever@eecs.umich.edu return ' '.join([el.ini_str() for el in self.elements]) 19263105Sstever@eecs.umich.edu 19279017Sandreas.hansson@arm.com # for config.json 19289017Sandreas.hansson@arm.com def get_config_as_dict(self): 19299017Sandreas.hansson@arm.com return {'role' : self.role, 19309017Sandreas.hansson@arm.com 'peer' : [el.ini_str() for el in self.elements]} 19319017Sandreas.hansson@arm.com 19323105Sstever@eecs.umich.edu def __getitem__(self, key): 19333105Sstever@eecs.umich.edu if not isinstance(key, int): 19343105Sstever@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 19353105Sstever@eecs.umich.edu if key >= len(self.elements): 19363105Sstever@eecs.umich.edu # need to extend list 19378839Sandreas.hansson@arm.com ext = [VectorPortElementRef(self.simobj, self.name, self.role, i) 19383105Sstever@eecs.umich.edu for i in range(len(self.elements), key+1)] 19393105Sstever@eecs.umich.edu self.elements.extend(ext) 19403105Sstever@eecs.umich.edu return self.elements[key] 19413105Sstever@eecs.umich.edu 19423105Sstever@eecs.umich.edu def _get_next(self): 19433105Sstever@eecs.umich.edu return self[len(self.elements)] 19443105Sstever@eecs.umich.edu 19453105Sstever@eecs.umich.edu def __setitem__(self, key, value): 19463105Sstever@eecs.umich.edu if not isinstance(key, int): 19473105Sstever@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 19483105Sstever@eecs.umich.edu self[key].connect(value) 19493105Sstever@eecs.umich.edu 19503105Sstever@eecs.umich.edu def connect(self, other): 19513109Sstever@eecs.umich.edu if isinstance(other, (list, tuple)): 19523109Sstever@eecs.umich.edu # Assign list of port refs to vector port. 19533109Sstever@eecs.umich.edu # For now, append them... not sure if that's the right semantics 19543109Sstever@eecs.umich.edu # or if it should replace the current vector. 19553109Sstever@eecs.umich.edu for ref in other: 19563109Sstever@eecs.umich.edu self._get_next().connect(ref) 19573109Sstever@eecs.umich.edu else: 19583109Sstever@eecs.umich.edu # scalar assignment to plain VectorPort is implicit append 19593109Sstever@eecs.umich.edu self._get_next().connect(other) 19603109Sstever@eecs.umich.edu 19613109Sstever@eecs.umich.edu def clone(self, simobj, memo): 19623109Sstever@eecs.umich.edu if memo.has_key(self): 19633109Sstever@eecs.umich.edu return memo[self] 19643109Sstever@eecs.umich.edu newRef = copy.copy(self) 19653109Sstever@eecs.umich.edu memo[self] = newRef 19663109Sstever@eecs.umich.edu newRef.simobj = simobj 19673109Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 19683109Sstever@eecs.umich.edu newRef.elements = [el.clone(simobj, memo) for el in self.elements] 19693109Sstever@eecs.umich.edu return newRef 19703105Sstever@eecs.umich.edu 19713105Sstever@eecs.umich.edu def unproxy(self, simobj): 19723105Sstever@eecs.umich.edu [el.unproxy(simobj) for el in self.elements] 19733105Sstever@eecs.umich.edu 19743105Sstever@eecs.umich.edu def ccConnect(self): 19753105Sstever@eecs.umich.edu [el.ccConnect() for el in self.elements] 19763105Sstever@eecs.umich.edu 19773101Sstever@eecs.umich.edu# Port description object. Like a ParamDesc object, this represents a 19783101Sstever@eecs.umich.edu# logical port in the SimObject class, not a particular port on a 19793101Sstever@eecs.umich.edu# SimObject instance. The latter are represented by PortRef objects. 19803101Sstever@eecs.umich.educlass Port(object): 19813101Sstever@eecs.umich.edu # Generate a PortRef for this port on the given SimObject with the 19823101Sstever@eecs.umich.edu # given name 19833105Sstever@eecs.umich.edu def makeRef(self, simobj): 19848839Sandreas.hansson@arm.com return PortRef(simobj, self.name, self.role) 19853101Sstever@eecs.umich.edu 19863101Sstever@eecs.umich.edu # Connect an instance of this port (on the given SimObject with 19873101Sstever@eecs.umich.edu # the given name) with the port described by the supplied PortRef 19883105Sstever@eecs.umich.edu def connect(self, simobj, ref): 19893105Sstever@eecs.umich.edu self.makeRef(simobj).connect(ref) 19903101Sstever@eecs.umich.edu 19918840Sandreas.hansson@arm.com # No need for any pre-declarations at the moment as we merely rely 19928840Sandreas.hansson@arm.com # on an unsigned int. 19938840Sandreas.hansson@arm.com def cxx_predecls(self, code): 19948840Sandreas.hansson@arm.com pass 19958840Sandreas.hansson@arm.com 199611988Sandreas.sandberg@arm.com def pybind_predecls(self, code): 199711988Sandreas.sandberg@arm.com cls.cxx_predecls(self, code) 199811988Sandreas.sandberg@arm.com 19998840Sandreas.hansson@arm.com # Declare an unsigned int with the same name as the port, that 20008840Sandreas.hansson@arm.com # will eventually hold the number of connected ports (and thus the 20018840Sandreas.hansson@arm.com # number of elements for a VectorPort). 20028840Sandreas.hansson@arm.com def cxx_decl(self, code): 20038840Sandreas.hansson@arm.com code('unsigned int port_${{self.name}}_connection_count;') 20048840Sandreas.hansson@arm.com 20058839Sandreas.hansson@arm.comclass MasterPort(Port): 20068839Sandreas.hansson@arm.com # MasterPort("description") 20078839Sandreas.hansson@arm.com def __init__(self, *args): 20088839Sandreas.hansson@arm.com if len(args) == 1: 20098839Sandreas.hansson@arm.com self.desc = args[0] 20108839Sandreas.hansson@arm.com self.role = 'MASTER' 20118839Sandreas.hansson@arm.com else: 20128839Sandreas.hansson@arm.com raise TypeError, 'wrong number of arguments' 20138839Sandreas.hansson@arm.com 20148839Sandreas.hansson@arm.comclass SlavePort(Port): 20158839Sandreas.hansson@arm.com # SlavePort("description") 20168839Sandreas.hansson@arm.com def __init__(self, *args): 20178839Sandreas.hansson@arm.com if len(args) == 1: 20188839Sandreas.hansson@arm.com self.desc = args[0] 20198839Sandreas.hansson@arm.com self.role = 'SLAVE' 20208839Sandreas.hansson@arm.com else: 20218839Sandreas.hansson@arm.com raise TypeError, 'wrong number of arguments' 20228839Sandreas.hansson@arm.com 20233101Sstever@eecs.umich.edu# VectorPort description object. Like Port, but represents a vector 202410405Sandreas.hansson@arm.com# of connections (e.g., as on a XBar). 20253101Sstever@eecs.umich.educlass VectorPort(Port): 20263105Sstever@eecs.umich.edu def __init__(self, *args): 20273101Sstever@eecs.umich.edu self.isVec = True 20283101Sstever@eecs.umich.edu 20293105Sstever@eecs.umich.edu def makeRef(self, simobj): 20308839Sandreas.hansson@arm.com return VectorPortRef(simobj, self.name, self.role) 20318839Sandreas.hansson@arm.com 20328839Sandreas.hansson@arm.comclass VectorMasterPort(VectorPort): 20338839Sandreas.hansson@arm.com # VectorMasterPort("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 VectorPort.__init__(self, *args) 20398839Sandreas.hansson@arm.com else: 20408839Sandreas.hansson@arm.com raise TypeError, 'wrong number of arguments' 20418839Sandreas.hansson@arm.com 20428839Sandreas.hansson@arm.comclass VectorSlavePort(VectorPort): 20438839Sandreas.hansson@arm.com # VectorSlavePort("description") 20448839Sandreas.hansson@arm.com def __init__(self, *args): 20458839Sandreas.hansson@arm.com if len(args) == 1: 20468839Sandreas.hansson@arm.com self.desc = args[0] 20478839Sandreas.hansson@arm.com self.role = 'SLAVE' 20488839Sandreas.hansson@arm.com VectorPort.__init__(self, *args) 20498839Sandreas.hansson@arm.com else: 20508839Sandreas.hansson@arm.com raise TypeError, 'wrong number of arguments' 20513105Sstever@eecs.umich.edu 20523109Sstever@eecs.umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 20533109Sstever@eecs.umich.edu# proxy objects (via set_param_desc()) so that proxy error messages 20543109Sstever@eecs.umich.edu# make sense. 20553109Sstever@eecs.umich.educlass PortParamDesc(object): 20563109Sstever@eecs.umich.edu __metaclass__ = Singleton 20573109Sstever@eecs.umich.edu 20583109Sstever@eecs.umich.edu ptype_str = 'Port' 20593109Sstever@eecs.umich.edu ptype = Port 20603105Sstever@eecs.umich.edu 20616654Snate@binkert.orgbaseEnums = allEnums.copy() 20626654Snate@binkert.orgbaseParams = allParams.copy() 20636654Snate@binkert.org 20646654Snate@binkert.orgdef clear(): 20656654Snate@binkert.org global allEnums, allParams 20666654Snate@binkert.org 20676654Snate@binkert.org allEnums = baseEnums.copy() 20686654Snate@binkert.org allParams = baseParams.copy() 20696654Snate@binkert.org 20703101Sstever@eecs.umich.edu__all__ = ['Param', 'VectorParam', 20713101Sstever@eecs.umich.edu 'Enum', 'Bool', 'String', 'Float', 20723101Sstever@eecs.umich.edu 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 20733101Sstever@eecs.umich.edu 'Int32', 'UInt32', 'Int64', 'UInt64', 20743101Sstever@eecs.umich.edu 'Counter', 'Addr', 'Tick', 'Percent', 20753101Sstever@eecs.umich.edu 'TcpPort', 'UdpPort', 'EthernetAddr', 20767777Sgblack@eecs.umich.edu 'IpAddress', 'IpNetmask', 'IpWithPort', 20773101Sstever@eecs.umich.edu 'MemorySize', 'MemorySize32', 20789827Sakash.bagdia@arm.com 'Latency', 'Frequency', 'Clock', 'Voltage', 20793101Sstever@eecs.umich.edu 'NetworkBandwidth', 'MemoryBandwidth', 20809232Sandreas.hansson@arm.com 'AddrRange', 20813101Sstever@eecs.umich.edu 'MaxAddr', 'MaxTick', 'AllMemory', 20823885Sbinkertn@umich.edu 'Time', 20833102Sstever@eecs.umich.edu 'NextEthernetAddr', 'NULL', 20848839Sandreas.hansson@arm.com 'MasterPort', 'SlavePort', 20858839Sandreas.hansson@arm.com 'VectorMasterPort', 'VectorSlavePort'] 20866654Snate@binkert.org 20876654Snate@binkert.orgimport SimObject 2088