params.py revision 13716
111988Sandreas.sandberg@arm.com# Copyright (c) 2012-2014, 2017, 2018 ARM Limited 28839Sandreas.hansson@arm.com# All rights reserved. 38839Sandreas.hansson@arm.com# 48839Sandreas.hansson@arm.com# The license below extends only to copyright in the software and shall 58839Sandreas.hansson@arm.com# not be construed as granting a license to any other intellectual 68839Sandreas.hansson@arm.com# property including but not limited to intellectual property relating 78839Sandreas.hansson@arm.com# to a hardware implementation of the functionality of the software 88839Sandreas.hansson@arm.com# licensed hereunder. You may use the software subject to the license 98839Sandreas.hansson@arm.com# terms below provided that you ensure that this notice is replicated 108839Sandreas.hansson@arm.com# unmodified and in its entirety in all distributions of the software, 118839Sandreas.hansson@arm.com# modified or unmodified, in source code or in binary form. 128839Sandreas.hansson@arm.com# 133101Sstever@eecs.umich.edu# Copyright (c) 2004-2006 The Regents of The University of Michigan 148579Ssteve.reinhardt@amd.com# Copyright (c) 2010-2011 Advanced Micro Devices, Inc. 153101Sstever@eecs.umich.edu# All rights reserved. 163101Sstever@eecs.umich.edu# 173101Sstever@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 183101Sstever@eecs.umich.edu# modification, are permitted provided that the following conditions are 193101Sstever@eecs.umich.edu# met: redistributions of source code must retain the above copyright 203101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 213101Sstever@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 223101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 233101Sstever@eecs.umich.edu# documentation and/or other materials provided with the distribution; 243101Sstever@eecs.umich.edu# neither the name of the copyright holders nor the names of its 253101Sstever@eecs.umich.edu# contributors may be used to endorse or promote products derived from 263101Sstever@eecs.umich.edu# this software without specific prior written permission. 273101Sstever@eecs.umich.edu# 283101Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 293101Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 303101Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 313101Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 323101Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 333101Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 343101Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 353101Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 363101Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 373101Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 383101Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 393101Sstever@eecs.umich.edu# 403101Sstever@eecs.umich.edu# Authors: Steve Reinhardt 413101Sstever@eecs.umich.edu# Nathan Binkert 427778Sgblack@eecs.umich.edu# Gabe Black 438839Sandreas.hansson@arm.com# Andreas Hansson 443101Sstever@eecs.umich.edu 453101Sstever@eecs.umich.edu##################################################################### 463101Sstever@eecs.umich.edu# 473101Sstever@eecs.umich.edu# Parameter description classes 483101Sstever@eecs.umich.edu# 493101Sstever@eecs.umich.edu# The _params dictionary in each class maps parameter names to either 503101Sstever@eecs.umich.edu# a Param or a VectorParam object. These objects contain the 513101Sstever@eecs.umich.edu# parameter description string, the parameter type, and the default 523101Sstever@eecs.umich.edu# value (if any). The convert() method on these objects is used to 533101Sstever@eecs.umich.edu# force whatever value is assigned to the parameter to the appropriate 543101Sstever@eecs.umich.edu# type. 553101Sstever@eecs.umich.edu# 563101Sstever@eecs.umich.edu# Note that the default values are loaded into the class's attribute 573101Sstever@eecs.umich.edu# space when the parameter dictionary is initialized (in 583101Sstever@eecs.umich.edu# MetaSimObject._new_param()); after that point they aren't used. 593101Sstever@eecs.umich.edu# 603101Sstever@eecs.umich.edu##################################################################### 613101Sstever@eecs.umich.edu 623885Sbinkertn@umich.edufrom __future__ import print_function 633885Sbinkertn@umich.edu 644762Snate@binkert.orgimport copy 653885Sbinkertn@umich.eduimport datetime 663885Sbinkertn@umich.eduimport re 677528Ssteve.reinhardt@amd.comimport sys 683885Sbinkertn@umich.eduimport time 694380Sbinkertn@umich.eduimport math 704167Sbinkertn@umich.edu 713102Sstever@eecs.umich.edufrom . import proxy 723101Sstever@eecs.umich.edufrom . import ticks 734762Snate@binkert.orgfrom .util import * 744762Snate@binkert.org 754762Snate@binkert.orgdef isSimObject(*args, **kwargs): 764762Snate@binkert.org from . import SimObject 774762Snate@binkert.org return SimObject.isSimObject(*args, **kwargs) 784762Snate@binkert.org 794762Snate@binkert.orgdef isSimObjectSequence(*args, **kwargs): 804762Snate@binkert.org from . import SimObject 814762Snate@binkert.org return SimObject.isSimObjectSequence(*args, **kwargs) 825033Smilesck@eecs.umich.edu 835033Smilesck@eecs.umich.edudef isSimObjectClass(*args, **kwargs): 845033Smilesck@eecs.umich.edu from . import SimObject 855033Smilesck@eecs.umich.edu return SimObject.isSimObjectClass(*args, **kwargs) 865033Smilesck@eecs.umich.edu 875033Smilesck@eecs.umich.eduallParams = {} 885033Smilesck@eecs.umich.edu 895033Smilesck@eecs.umich.educlass MetaParamValue(type): 905033Smilesck@eecs.umich.edu def __new__(mcls, name, bases, dct): 915033Smilesck@eecs.umich.edu cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) 923101Sstever@eecs.umich.edu assert name not in allParams 933101Sstever@eecs.umich.edu allParams[name] = cls 943101Sstever@eecs.umich.edu return cls 955033Smilesck@eecs.umich.edu 9610267SGeoffrey.Blake@arm.com 978596Ssteve.reinhardt@amd.com# Dummy base class to identify types that are legitimate for SimObject 988596Ssteve.reinhardt@amd.com# parameters. 998596Ssteve.reinhardt@amd.comclass ParamValue(object): 1008596Ssteve.reinhardt@amd.com __metaclass__ = MetaParamValue 1017673Snate@binkert.org cmd_line_settable = False 1027673Snate@binkert.org 1037673Snate@binkert.org # Generate the code needed as a prerequisite for declaring a C++ 1047673Snate@binkert.org # object of this type. Typically generates one or more #include 10511988Sandreas.sandberg@arm.com # statements. Used when declaring parameters of this type. 10611988Sandreas.sandberg@arm.com @classmethod 10711988Sandreas.sandberg@arm.com def cxx_predecls(cls, code): 10811988Sandreas.sandberg@arm.com pass 1093101Sstever@eecs.umich.edu 1103101Sstever@eecs.umich.edu @classmethod 1113101Sstever@eecs.umich.edu def pybind_predecls(cls, code): 1123101Sstever@eecs.umich.edu cls.cxx_predecls(code) 1133101Sstever@eecs.umich.edu 11410380SAndrew.Bardsley@arm.com # default for printing to .ini file is regular string conversion. 11510380SAndrew.Bardsley@arm.com # will be overridden in some cases 11610380SAndrew.Bardsley@arm.com def ini_str(self): 11710380SAndrew.Bardsley@arm.com return str(self) 11810380SAndrew.Bardsley@arm.com 11910380SAndrew.Bardsley@arm.com # default for printing to .json file is regular string conversion. 12010458Sandreas.hansson@arm.com # will be overridden in some cases, mostly to use native Python 12110458Sandreas.hansson@arm.com # types where there are similar JSON types 12210458Sandreas.hansson@arm.com def config_value(self): 12310458Sandreas.hansson@arm.com return str(self) 12410458Sandreas.hansson@arm.com 12510458Sandreas.hansson@arm.com # Prerequisites for .ini parsing with cxx_ini_parse 12610458Sandreas.hansson@arm.com @classmethod 12710458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 12810458Sandreas.hansson@arm.com pass 12910458Sandreas.hansson@arm.com 13010458Sandreas.hansson@arm.com # parse a .ini file entry for this param from string expression 13110458Sandreas.hansson@arm.com # src into lvalue dest (of the param's C++ type) 1323101Sstever@eecs.umich.edu @classmethod 1333101Sstever@eecs.umich.edu def cxx_ini_parse(cls, code, src, dest, ret): 1343101Sstever@eecs.umich.edu code('// Unhandled param type: %s' % cls.__name__) 1353101Sstever@eecs.umich.edu code('%s false;' % ret) 1363101Sstever@eecs.umich.edu 13710267SGeoffrey.Blake@arm.com # allows us to blithely call unproxy() on things without checking 13810267SGeoffrey.Blake@arm.com # if they're really proxies or not 13910267SGeoffrey.Blake@arm.com def unproxy(self, base): 14010267SGeoffrey.Blake@arm.com return self 1413101Sstever@eecs.umich.edu 1423101Sstever@eecs.umich.edu # Produce a human readable version of the stored value 1433101Sstever@eecs.umich.edu def pretty_print(self, value): 1443101Sstever@eecs.umich.edu return str(value) 1453101Sstever@eecs.umich.edu 1463101Sstever@eecs.umich.edu# Regular parameter description. 1473101Sstever@eecs.umich.educlass ParamDesc(object): 1483101Sstever@eecs.umich.edu def __init__(self, ptype_str, ptype, *args, **kwargs): 1493101Sstever@eecs.umich.edu self.ptype_str = ptype_str 1503101Sstever@eecs.umich.edu # remember ptype only if it is provided 1513101Sstever@eecs.umich.edu if ptype != None: 1523101Sstever@eecs.umich.edu self.ptype = ptype 1533101Sstever@eecs.umich.edu 1543101Sstever@eecs.umich.edu if args: 1553101Sstever@eecs.umich.edu if len(args) == 1: 1563101Sstever@eecs.umich.edu self.desc = args[0] 1573101Sstever@eecs.umich.edu elif len(args) == 2: 1583101Sstever@eecs.umich.edu self.default = args[0] 1593101Sstever@eecs.umich.edu self.desc = args[1] 1603101Sstever@eecs.umich.edu else: 1613101Sstever@eecs.umich.edu raise TypeError('too many arguments') 1623101Sstever@eecs.umich.edu 1633101Sstever@eecs.umich.edu if 'desc' in kwargs: 1643101Sstever@eecs.umich.edu assert(not hasattr(self, 'desc')) 1653101Sstever@eecs.umich.edu self.desc = kwargs['desc'] 1663101Sstever@eecs.umich.edu del kwargs['desc'] 1673101Sstever@eecs.umich.edu 1683101Sstever@eecs.umich.edu if 'default' in kwargs: 1693101Sstever@eecs.umich.edu assert(not hasattr(self, 'default')) 1703101Sstever@eecs.umich.edu self.default = kwargs['default'] 1713101Sstever@eecs.umich.edu del kwargs['default'] 1723101Sstever@eecs.umich.edu 1733101Sstever@eecs.umich.edu if kwargs: 1743101Sstever@eecs.umich.edu raise TypeError('extra unknown kwargs %s' % kwargs) 1753101Sstever@eecs.umich.edu 1765033Smilesck@eecs.umich.edu if not hasattr(self, 'desc'): 1776656Snate@binkert.org raise TypeError('desc attribute missing') 1785033Smilesck@eecs.umich.edu 1795033Smilesck@eecs.umich.edu def __getattr__(self, attr): 1805033Smilesck@eecs.umich.edu if attr == 'ptype': 1813101Sstever@eecs.umich.edu from . import SimObject 1823101Sstever@eecs.umich.edu ptype = SimObject.allClasses[self.ptype_str] 1833101Sstever@eecs.umich.edu assert isSimObjectClass(ptype) 18410267SGeoffrey.Blake@arm.com self.ptype = ptype 18510267SGeoffrey.Blake@arm.com return ptype 18610267SGeoffrey.Blake@arm.com 18710267SGeoffrey.Blake@arm.com raise AttributeError("'%s' object has no attribute '%s'" % \ 18810267SGeoffrey.Blake@arm.com (type(self).__name__, attr)) 18910267SGeoffrey.Blake@arm.com 19010267SGeoffrey.Blake@arm.com def example_str(self): 19110267SGeoffrey.Blake@arm.com if hasattr(self.ptype, "ex_str"): 19210267SGeoffrey.Blake@arm.com return self.ptype.ex_str 19310267SGeoffrey.Blake@arm.com else: 19410267SGeoffrey.Blake@arm.com return self.ptype_str 19510267SGeoffrey.Blake@arm.com 19610267SGeoffrey.Blake@arm.com # Is the param available to be exposed on the command line 1973101Sstever@eecs.umich.edu def isCmdLineSettable(self): 1983101Sstever@eecs.umich.edu if hasattr(self.ptype, "cmd_line_settable"): 1993101Sstever@eecs.umich.edu return self.ptype.cmd_line_settable 2003101Sstever@eecs.umich.edu else: 2013101Sstever@eecs.umich.edu return False 2023101Sstever@eecs.umich.edu 2033101Sstever@eecs.umich.edu def convert(self, value): 2043101Sstever@eecs.umich.edu if isinstance(value, proxy.BaseProxy): 2053101Sstever@eecs.umich.edu value.set_param_desc(self) 2063101Sstever@eecs.umich.edu return value 2073102Sstever@eecs.umich.edu if 'ptype' not in self.__dict__ and isNullPointer(value): 2083101Sstever@eecs.umich.edu # deferred evaluation of SimObject; continue to defer if 2093101Sstever@eecs.umich.edu # we're just assigning a null pointer 2103101Sstever@eecs.umich.edu return value 21110267SGeoffrey.Blake@arm.com if isinstance(value, self.ptype): 21210267SGeoffrey.Blake@arm.com return value 21310267SGeoffrey.Blake@arm.com if isNullPointer(value) and isSimObjectClass(self.ptype): 21410267SGeoffrey.Blake@arm.com return value 21510267SGeoffrey.Blake@arm.com return self.ptype(value) 21610267SGeoffrey.Blake@arm.com 21710267SGeoffrey.Blake@arm.com def pretty_print(self, value): 2187673Snate@binkert.org if isinstance(value, proxy.BaseProxy): 2198607Sgblack@eecs.umich.edu return str(value) 2207673Snate@binkert.org if isNullPointer(value): 2213101Sstever@eecs.umich.edu return NULL 22211988Sandreas.sandberg@arm.com return self.ptype(value).pretty_print(value) 22311988Sandreas.sandberg@arm.com 22411988Sandreas.sandberg@arm.com def cxx_predecls(self, code): 2257673Snate@binkert.org code('#include <cstddef>') 2267673Snate@binkert.org self.ptype.cxx_predecls(code) 2273101Sstever@eecs.umich.edu 2283101Sstever@eecs.umich.edu def pybind_predecls(self, code): 2293101Sstever@eecs.umich.edu self.ptype.pybind_predecls(code) 2303101Sstever@eecs.umich.edu 2313101Sstever@eecs.umich.edu def cxx_decl(self, code): 2323101Sstever@eecs.umich.edu code('${{self.ptype.cxx_type}} ${{self.name}};') 2335033Smilesck@eecs.umich.edu 2345475Snate@binkert.org# Vector-valued parameter description. Just like ParamDesc, except 2355475Snate@binkert.org# that the value is a vector (list) of the specified type instead of a 2365475Snate@binkert.org# single value. 2375475Snate@binkert.org 23810380SAndrew.Bardsley@arm.comclass VectorParamValue(list): 23910380SAndrew.Bardsley@arm.com __metaclass__ = MetaParamValue 24010380SAndrew.Bardsley@arm.com def __setattr__(self, attr, value): 2413101Sstever@eecs.umich.edu raise AttributeError("Not allowed to set %s on '%s'" % \ 2423101Sstever@eecs.umich.edu (attr, type(self).__name__)) 2433101Sstever@eecs.umich.edu 2444762Snate@binkert.org def config_value(self): 2454762Snate@binkert.org return [v.config_value() for v in self] 2464762Snate@binkert.org 2473101Sstever@eecs.umich.edu def ini_str(self): 24812050Snikos.nikoleris@arm.com return ' '.join([v.ini_str() for v in self]) 24912050Snikos.nikoleris@arm.com 25012050Snikos.nikoleris@arm.com def getValue(self): 2518459SAli.Saidi@ARM.com return [ v.getValue() for v in self ] 2528459SAli.Saidi@ARM.com 25312050Snikos.nikoleris@arm.com def unproxy(self, base): 2543101Sstever@eecs.umich.edu if len(self) == 1 and isinstance(self[0], proxy.BaseProxy): 2557528Ssteve.reinhardt@amd.com # The value is a proxy (e.g. Parent.any, Parent.all or 2567528Ssteve.reinhardt@amd.com # Parent.x) therefore try resolve it 2577528Ssteve.reinhardt@amd.com return self[0].unproxy(base) 2587528Ssteve.reinhardt@amd.com else: 2597528Ssteve.reinhardt@amd.com return [v.unproxy(base) for v in self] 2607528Ssteve.reinhardt@amd.com 2613101Sstever@eecs.umich.educlass SimObjectVector(VectorParamValue): 2627528Ssteve.reinhardt@amd.com # support clone operation 2637528Ssteve.reinhardt@amd.com def __call__(self, **kwargs): 2647528Ssteve.reinhardt@amd.com return SimObjectVector([v(**kwargs) for v in self]) 2657528Ssteve.reinhardt@amd.com 2667528Ssteve.reinhardt@amd.com def clear_parent(self, old_parent): 2677528Ssteve.reinhardt@amd.com for v in self: 2687528Ssteve.reinhardt@amd.com v.clear_parent(old_parent) 2697528Ssteve.reinhardt@amd.com 2707528Ssteve.reinhardt@amd.com def set_parent(self, parent, name): 2717528Ssteve.reinhardt@amd.com if len(self) == 1: 2728321Ssteve.reinhardt@amd.com self[0].set_parent(parent, name) 27312194Sgabeblack@google.com else: 2747528Ssteve.reinhardt@amd.com width = int(math.ceil(math.log(len(self))/math.log(10))) 2757528Ssteve.reinhardt@amd.com for i,v in enumerate(self): 2767528Ssteve.reinhardt@amd.com v.set_parent(parent, "%s%0*d" % (name, width, i)) 2777528Ssteve.reinhardt@amd.com 2787528Ssteve.reinhardt@amd.com def has_parent(self): 2797528Ssteve.reinhardt@amd.com return any([e.has_parent() for e in self if not isNullPointer(e)]) 2807528Ssteve.reinhardt@amd.com 2817528Ssteve.reinhardt@amd.com # return 'cpu0 cpu1' etc. for print_ini() 2827528Ssteve.reinhardt@amd.com def get_name(self): 2837528Ssteve.reinhardt@amd.com return ' '.join([v._name for v in self]) 2847528Ssteve.reinhardt@amd.com 2857528Ssteve.reinhardt@amd.com # By iterating through the constituent members of the vector here 2867528Ssteve.reinhardt@amd.com # we can nicely handle iterating over all a SimObject's children 2873101Sstever@eecs.umich.edu # without having to provide lots of special functions on 2888664SAli.Saidi@ARM.com # SimObjectVector directly. 2898664SAli.Saidi@ARM.com def descendants(self): 2908664SAli.Saidi@ARM.com for v in self: 2918664SAli.Saidi@ARM.com for obj in v.descendants(): 2928664SAli.Saidi@ARM.com yield obj 2938664SAli.Saidi@ARM.com 2949953Sgeoffrey.blake@arm.com def get_config_as_dict(self): 2959953Sgeoffrey.blake@arm.com a = [] 2969953Sgeoffrey.blake@arm.com for v in self: 2979953Sgeoffrey.blake@arm.com a.append(v.get_config_as_dict()) 2989953Sgeoffrey.blake@arm.com return a 2999953Sgeoffrey.blake@arm.com 3009953Sgeoffrey.blake@arm.com # If we are replacing an item in the vector, make sure to set the 3019953Sgeoffrey.blake@arm.com # parent reference of the new SimObject to be the same as the parent 3029953Sgeoffrey.blake@arm.com # of the SimObject being replaced. Useful to have if we created 3039953Sgeoffrey.blake@arm.com # a SimObjectVector of temporary objects that will be modified later in 3049953Sgeoffrey.blake@arm.com # configuration scripts. 3059953Sgeoffrey.blake@arm.com def __setitem__(self, key, value): 3069953Sgeoffrey.blake@arm.com val = self[key] 30710267SGeoffrey.Blake@arm.com if value.has_parent(): 30810267SGeoffrey.Blake@arm.com warn("SimObject %s already has a parent" % value.get_name() +\ 30910267SGeoffrey.Blake@arm.com " that is being overwritten by a SimObjectVector") 31010267SGeoffrey.Blake@arm.com value.set_parent(val.get_parent(), val._name) 31110267SGeoffrey.Blake@arm.com super(SimObjectVector, self).__setitem__(key, value) 31210267SGeoffrey.Blake@arm.com 31310267SGeoffrey.Blake@arm.com # Enumerate the params of each member of the SimObject vector. Creates 31410267SGeoffrey.Blake@arm.com # strings that will allow indexing into the vector by the python code and 31510267SGeoffrey.Blake@arm.com # allow it to be specified on the command line. 31610267SGeoffrey.Blake@arm.com def enumerateParams(self, flags_dict = {}, 31710267SGeoffrey.Blake@arm.com cmd_line_str = "", 31810267SGeoffrey.Blake@arm.com access_str = ""): 31910267SGeoffrey.Blake@arm.com if hasattr(self, "_paramEnumed"): 32010267SGeoffrey.Blake@arm.com print("Cycle detected enumerating params at %s?!" % (cmd_line_str)) 32110267SGeoffrey.Blake@arm.com else: 32210267SGeoffrey.Blake@arm.com x = 0 32310267SGeoffrey.Blake@arm.com for vals in self: 32410267SGeoffrey.Blake@arm.com # Each entry in the SimObjectVector should be an 32510267SGeoffrey.Blake@arm.com # instance of a SimObject 32610267SGeoffrey.Blake@arm.com flags_dict = vals.enumerateParams(flags_dict, 3273101Sstever@eecs.umich.edu cmd_line_str + "%d." % x, 3283101Sstever@eecs.umich.edu access_str + "[%d]." % x) 3293101Sstever@eecs.umich.edu x = x + 1 3303101Sstever@eecs.umich.edu 3313101Sstever@eecs.umich.edu return flags_dict 3323101Sstever@eecs.umich.edu 3333101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc): 33410364SGeoffrey.Blake@arm.com # Convert assigned value to appropriate type. If the RHS is not a 33510364SGeoffrey.Blake@arm.com # list or tuple, it generates a single-element list. 33610364SGeoffrey.Blake@arm.com def convert(self, value): 33710364SGeoffrey.Blake@arm.com if isinstance(value, (list, tuple)): 3383101Sstever@eecs.umich.edu # list: coerce each element into new list 3394762Snate@binkert.org tmp_list = [ ParamDesc.convert(self, v) for v in value ] 3404762Snate@binkert.org elif isinstance(value, str): 3414762Snate@binkert.org # If input is a csv string 3424762Snate@binkert.org tmp_list = [ ParamDesc.convert(self, v) \ 3437528Ssteve.reinhardt@amd.com for v in value.strip('[').strip(']').split(',') ] 3444762Snate@binkert.org else: 3454762Snate@binkert.org # singleton: coerce to a single-element list 3464762Snate@binkert.org tmp_list = [ ParamDesc.convert(self, value) ] 34710267SGeoffrey.Blake@arm.com 34810267SGeoffrey.Blake@arm.com if isSimObjectSequence(tmp_list): 34910267SGeoffrey.Blake@arm.com return SimObjectVector(tmp_list) 35010267SGeoffrey.Blake@arm.com else: 35110267SGeoffrey.Blake@arm.com return VectorParamValue(tmp_list) 35210267SGeoffrey.Blake@arm.com 35310267SGeoffrey.Blake@arm.com # Produce a human readable example string that describes 35410267SGeoffrey.Blake@arm.com # how to set this vector parameter in the absence of a default 35510267SGeoffrey.Blake@arm.com # value. 35610267SGeoffrey.Blake@arm.com def example_str(self): 35710267SGeoffrey.Blake@arm.com s = super(VectorParamDesc, self).example_str() 35810267SGeoffrey.Blake@arm.com help_str = "[" + s + "," + s + ", ...]" 35910267SGeoffrey.Blake@arm.com return help_str 36010267SGeoffrey.Blake@arm.com 36110267SGeoffrey.Blake@arm.com # Produce a human readable representation of the value of this vector param. 36210267SGeoffrey.Blake@arm.com def pretty_print(self, value): 36310267SGeoffrey.Blake@arm.com if isinstance(value, (list, tuple)): 36410267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ] 36510267SGeoffrey.Blake@arm.com elif isinstance(value, str): 36610267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ] 36710267SGeoffrey.Blake@arm.com else: 36810267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, value) ] 36910267SGeoffrey.Blake@arm.com 37010267SGeoffrey.Blake@arm.com return tmp_list 37110267SGeoffrey.Blake@arm.com 37210267SGeoffrey.Blake@arm.com # This is a helper function for the new config system 37310364SGeoffrey.Blake@arm.com def __call__(self, value): 37410364SGeoffrey.Blake@arm.com if isinstance(value, (list, tuple)): 37510267SGeoffrey.Blake@arm.com # list: coerce each element into new list 37610267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) for v in value ] 37710267SGeoffrey.Blake@arm.com elif isinstance(value, str): 37810267SGeoffrey.Blake@arm.com # If input is a csv string 37910267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) \ 38010267SGeoffrey.Blake@arm.com for v in value.strip('[').strip(']').split(',') ] 3817673Snate@binkert.org else: 3827673Snate@binkert.org # singleton: coerce to a single-element list 3837673Snate@binkert.org tmp_list = [ ParamDesc.convert(self, value) ] 3843101Sstever@eecs.umich.edu 38511988Sandreas.sandberg@arm.com return VectorParamValue(tmp_list) 38611988Sandreas.sandberg@arm.com 38711988Sandreas.sandberg@arm.com def cxx_predecls(self, code): 38811988Sandreas.sandberg@arm.com code('#include <vector>') 3897673Snate@binkert.org self.ptype.cxx_predecls(code) 3907673Snate@binkert.org 3913101Sstever@eecs.umich.edu def pybind_predecls(self, code): 3923101Sstever@eecs.umich.edu code('#include <vector>') 3933101Sstever@eecs.umich.edu self.ptype.pybind_predecls(code) 3943101Sstever@eecs.umich.edu 3953101Sstever@eecs.umich.edu def cxx_decl(self, code): 3963101Sstever@eecs.umich.edu code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};') 3973101Sstever@eecs.umich.edu 3983101Sstever@eecs.umich.educlass ParamFactory(object): 3993101Sstever@eecs.umich.edu def __init__(self, param_desc_class, ptype_str = None): 4003101Sstever@eecs.umich.edu self.param_desc_class = param_desc_class 4013101Sstever@eecs.umich.edu self.ptype_str = ptype_str 4023101Sstever@eecs.umich.edu 4033101Sstever@eecs.umich.edu def __getattr__(self, attr): 4043101Sstever@eecs.umich.edu if self.ptype_str: 4053101Sstever@eecs.umich.edu attr = self.ptype_str + '.' + attr 4065033Smilesck@eecs.umich.edu return ParamFactory(self.param_desc_class, attr) 4075033Smilesck@eecs.umich.edu 4083101Sstever@eecs.umich.edu # E.g., Param.Int(5, "number of widgets") 4093101Sstever@eecs.umich.edu def __call__(self, *args, **kwargs): 4103101Sstever@eecs.umich.edu ptype = None 4113101Sstever@eecs.umich.edu try: 4123101Sstever@eecs.umich.edu ptype = allParams[self.ptype_str] 4133101Sstever@eecs.umich.edu except KeyError: 4143101Sstever@eecs.umich.edu # if name isn't defined yet, assume it's a SimObject, and 4153101Sstever@eecs.umich.edu # try to resolve it later 4163101Sstever@eecs.umich.edu pass 4173101Sstever@eecs.umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 4183101Sstever@eecs.umich.edu 4193101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc) 4203101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc) 4213101Sstever@eecs.umich.edu 4223101Sstever@eecs.umich.edu##################################################################### 4233101Sstever@eecs.umich.edu# 4243101Sstever@eecs.umich.edu# Parameter Types 4253101Sstever@eecs.umich.edu# 4263101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types 4273101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more 4283101Sstever@eecs.umich.edu# flexible to define our own set of types. This gives us more control 4293101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the 4303101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via 4313101Sstever@eecs.umich.edu# the __str__() conversion method). 4323101Sstever@eecs.umich.edu# 43310267SGeoffrey.Blake@arm.com##################################################################### 4347673Snate@binkert.org 4357673Snate@binkert.org# String-valued parameter. Just mixin the ParamValue class with the 4367673Snate@binkert.org# built-in str class. 4377673Snate@binkert.orgclass String(ParamValue,str): 4387673Snate@binkert.org cxx_type = 'std::string' 43910267SGeoffrey.Blake@arm.com cmd_line_settable = True 44010267SGeoffrey.Blake@arm.com 44110267SGeoffrey.Blake@arm.com @classmethod 44210267SGeoffrey.Blake@arm.com def cxx_predecls(self, code): 44310458Sandreas.hansson@arm.com code('#include <string>') 44410458Sandreas.hansson@arm.com 44510458Sandreas.hansson@arm.com def __call__(self, value): 44610458Sandreas.hansson@arm.com self = value 44710458Sandreas.hansson@arm.com return value 4484762Snate@binkert.org 4494762Snate@binkert.org @classmethod 4503101Sstever@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 4513101Sstever@eecs.umich.edu code('%s = %s;' % (dest, src)) 4523101Sstever@eecs.umich.edu code('%s true;' % ret) 4533101Sstever@eecs.umich.edu 4543101Sstever@eecs.umich.edu def getValue(self): 4553101Sstever@eecs.umich.edu return self 4563101Sstever@eecs.umich.edu 4573101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math 4583101Sstever@eecs.umich.edu# operations in a type-safe way. e.g., a Latency times an int returns 4593101Sstever@eecs.umich.edu# a new Latency object. 4603101Sstever@eecs.umich.educlass NumericParamValue(ParamValue): 4613714Sstever@eecs.umich.edu @staticmethod 4623714Sstever@eecs.umich.edu def unwrap(v): 4633714Sstever@eecs.umich.edu return v.value if isinstance(v, NumericParamValue) else v 4643714Sstever@eecs.umich.edu 4653714Sstever@eecs.umich.edu def __str__(self): 4663714Sstever@eecs.umich.edu return str(self.value) 4673101Sstever@eecs.umich.edu 4683101Sstever@eecs.umich.edu def __float__(self): 4693101Sstever@eecs.umich.edu return float(self.value) 4703101Sstever@eecs.umich.edu 4713101Sstever@eecs.umich.edu def __long__(self): 4723101Sstever@eecs.umich.edu return long(self.value) 4733101Sstever@eecs.umich.edu 4743101Sstever@eecs.umich.edu def __int__(self): 4753101Sstever@eecs.umich.edu return int(self.value) 4763101Sstever@eecs.umich.edu 4773101Sstever@eecs.umich.edu # hook for bounds checking 4783101Sstever@eecs.umich.edu def _check(self): 4793101Sstever@eecs.umich.edu return 4803101Sstever@eecs.umich.edu 4813101Sstever@eecs.umich.edu def __mul__(self, other): 4823101Sstever@eecs.umich.edu newobj = self.__class__(self) 4833101Sstever@eecs.umich.edu newobj.value *= NumericParamValue.unwrap(other) 4843101Sstever@eecs.umich.edu newobj._check() 4853101Sstever@eecs.umich.edu return newobj 4863101Sstever@eecs.umich.edu 4873101Sstever@eecs.umich.edu __rmul__ = __mul__ 4883101Sstever@eecs.umich.edu 4893101Sstever@eecs.umich.edu def __truediv__(self, other): 4903101Sstever@eecs.umich.edu newobj = self.__class__(self) 49110380SAndrew.Bardsley@arm.com newobj.value /= NumericParamValue.unwrap(other) 49210380SAndrew.Bardsley@arm.com newobj._check() 49310380SAndrew.Bardsley@arm.com return newobj 49410458Sandreas.hansson@arm.com 49510458Sandreas.hansson@arm.com def __floordiv__(self, other): 49610458Sandreas.hansson@arm.com newobj = self.__class__(self) 49710458Sandreas.hansson@arm.com newobj.value //= NumericParamValue.unwrap(other) 49810458Sandreas.hansson@arm.com newobj._check() 49910458Sandreas.hansson@arm.com return newobj 50010458Sandreas.hansson@arm.com 50110458Sandreas.hansson@arm.com 50210458Sandreas.hansson@arm.com def __add__(self, other): 50310458Sandreas.hansson@arm.com newobj = self.__class__(self) 50410458Sandreas.hansson@arm.com newobj.value += NumericParamValue.unwrap(other) 50510458Sandreas.hansson@arm.com newobj._check() 50610458Sandreas.hansson@arm.com return newobj 5073101Sstever@eecs.umich.edu 5085033Smilesck@eecs.umich.edu def __sub__(self, other): 5093101Sstever@eecs.umich.edu newobj = self.__class__(self) 5103101Sstever@eecs.umich.edu newobj.value -= NumericParamValue.unwrap(other) 5113101Sstever@eecs.umich.edu newobj._check() 5123101Sstever@eecs.umich.edu return newobj 5133101Sstever@eecs.umich.edu 5143101Sstever@eecs.umich.edu def __iadd__(self, other): 5153101Sstever@eecs.umich.edu self.value += NumericParamValue.unwrap(other) 5163101Sstever@eecs.umich.edu self._check() 5173101Sstever@eecs.umich.edu return self 5183101Sstever@eecs.umich.edu 5193101Sstever@eecs.umich.edu def __isub__(self, other): 5203101Sstever@eecs.umich.edu self.value -= NumericParamValue.unwrap(other) 5215822Ssaidi@eecs.umich.edu self._check() 5225822Ssaidi@eecs.umich.edu return self 5233101Sstever@eecs.umich.edu 5243101Sstever@eecs.umich.edu def __imul__(self, other): 5253101Sstever@eecs.umich.edu self.value *= NumericParamValue.unwrap(other) 5263101Sstever@eecs.umich.edu self._check() 5273101Sstever@eecs.umich.edu return self 5283101Sstever@eecs.umich.edu 5293101Sstever@eecs.umich.edu def __itruediv__(self, other): 5303101Sstever@eecs.umich.edu self.value /= NumericParamValue.unwrap(other) 5313101Sstever@eecs.umich.edu self._check() 5323101Sstever@eecs.umich.edu return self 5333101Sstever@eecs.umich.edu 5343101Sstever@eecs.umich.edu def __ifloordiv__(self, other): 5353101Sstever@eecs.umich.edu self.value //= NumericParamValue.unwrap(other) 53610267SGeoffrey.Blake@arm.com self._check() 5373101Sstever@eecs.umich.edu return self 5383101Sstever@eecs.umich.edu 5393101Sstever@eecs.umich.edu def __lt__(self, other): 5403101Sstever@eecs.umich.edu return self.value < NumericParamValue.unwrap(other) 5413101Sstever@eecs.umich.edu 5423101Sstever@eecs.umich.edu # Python 2.7 pre __future__.division operators 5433101Sstever@eecs.umich.edu # TODO: Remove these when after "import division from __future__" 5443101Sstever@eecs.umich.edu __div__ = __truediv__ 5453102Sstever@eecs.umich.edu __idiv__ = __itruediv__ 5463714Sstever@eecs.umich.edu 5473101Sstever@eecs.umich.edu def config_value(self): 5483714Sstever@eecs.umich.edu return self.value 5493714Sstever@eecs.umich.edu 5503714Sstever@eecs.umich.edu @classmethod 5513101Sstever@eecs.umich.edu def cxx_ini_predecls(cls, code): 5523101Sstever@eecs.umich.edu # Assume that base/str.hh will be included anyway 55310267SGeoffrey.Blake@arm.com # code('#include "base/str.hh"') 55410267SGeoffrey.Blake@arm.com pass 55510267SGeoffrey.Blake@arm.com 55610267SGeoffrey.Blake@arm.com # The default for parsing PODs from an .ini entry is to extract from an 5577673Snate@binkert.org # istringstream and let overloading choose the right type according to 5587673Snate@binkert.org # the dest type. 5597673Snate@binkert.org @classmethod 5607673Snate@binkert.org def cxx_ini_parse(self, code, src, dest, ret): 5617673Snate@binkert.org code('%s to_number(%s, %s);' % (ret, src, dest)) 5624762Snate@binkert.org 5634762Snate@binkert.org# Metaclass for bounds-checked integer parameters. See CheckedInt. 5644762Snate@binkert.orgclass CheckedIntType(MetaParamValue): 5653101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 5663101Sstever@eecs.umich.edu super(CheckedIntType, cls).__init__(name, bases, dict) 5673101Sstever@eecs.umich.edu 5683101Sstever@eecs.umich.edu # CheckedInt is an abstract base class, so we actually don't 5693101Sstever@eecs.umich.edu # want to do any processing on it... the rest of this code is 5703101Sstever@eecs.umich.edu # just for classes that derive from CheckedInt. 5713101Sstever@eecs.umich.edu if name == 'CheckedInt': 5723101Sstever@eecs.umich.edu return 5733101Sstever@eecs.umich.edu 5743101Sstever@eecs.umich.edu if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 5753101Sstever@eecs.umich.edu if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 5763101Sstever@eecs.umich.edu panic("CheckedInt subclass %s must define either\n" \ 5773101Sstever@eecs.umich.edu " 'min' and 'max' or 'size' and 'unsigned'\n", 5783101Sstever@eecs.umich.edu name); 5793101Sstever@eecs.umich.edu if cls.unsigned: 5803101Sstever@eecs.umich.edu cls.min = 0 5813101Sstever@eecs.umich.edu cls.max = 2 ** cls.size - 1 5823101Sstever@eecs.umich.edu else: 5833101Sstever@eecs.umich.edu cls.min = -(2 ** (cls.size - 1)) 5849184Sandreas.hansson@arm.com cls.max = (2 ** (cls.size - 1)) - 1 5859184Sandreas.hansson@arm.com 5869184Sandreas.hansson@arm.com# Abstract superclass for bounds-checked integer parameters. This 5879184Sandreas.hansson@arm.com# class is subclassed to generate parameter classes with specific 5889184Sandreas.hansson@arm.com# bounds. Initialization of the min and max bounds is done in the 5899184Sandreas.hansson@arm.com# metaclass CheckedIntType.__init__. 59011802Sandreas.sandberg@arm.comclass CheckedInt(NumericParamValue): 5919184Sandreas.hansson@arm.com __metaclass__ = CheckedIntType 5929184Sandreas.hansson@arm.com cmd_line_settable = True 59310458Sandreas.hansson@arm.com 59410458Sandreas.hansson@arm.com def _check(self): 59510458Sandreas.hansson@arm.com if not self.min <= self.value <= self.max: 59610458Sandreas.hansson@arm.com raise TypeError('Integer param out of bounds %d < %d < %d' % \ 59710458Sandreas.hansson@arm.com (self.min, self.value, self.max)) 59810458Sandreas.hansson@arm.com 59910458Sandreas.hansson@arm.com def __init__(self, value): 60010458Sandreas.hansson@arm.com if isinstance(value, str): 60110458Sandreas.hansson@arm.com self.value = convert.toInteger(value) 60210458Sandreas.hansson@arm.com elif isinstance(value, (int, long, float, NumericParamValue)): 60310458Sandreas.hansson@arm.com self.value = long(value) 60410458Sandreas.hansson@arm.com else: 60510458Sandreas.hansson@arm.com raise TypeError("Can't convert object of type %s to CheckedInt" \ 60610458Sandreas.hansson@arm.com % type(value).__name__) 6073101Sstever@eecs.umich.edu self._check() 6084446Sbinkertn@umich.edu 60910668SGeoffrey.Blake@arm.com def __call__(self, value): 6103101Sstever@eecs.umich.edu self.__init__(value) 6115468Snate@binkert.org return value 61210267SGeoffrey.Blake@arm.com 6135468Snate@binkert.org def __index__(self): 6145468Snate@binkert.org return int(self.value) 6155468Snate@binkert.org 6165468Snate@binkert.org @classmethod 6175468Snate@binkert.org def cxx_predecls(cls, code): 61810267SGeoffrey.Blake@arm.com # most derived types require this, so we just do it here once 61910267SGeoffrey.Blake@arm.com code('#include "base/types.hh"') 62010267SGeoffrey.Blake@arm.com 62110267SGeoffrey.Blake@arm.com def getValue(self): 6224762Snate@binkert.org return long(self.value) 6234762Snate@binkert.org 6244762Snate@binkert.orgclass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 62510380SAndrew.Bardsley@arm.comclass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 62610380SAndrew.Bardsley@arm.com 62710380SAndrew.Bardsley@arm.comclass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 62810458Sandreas.hansson@arm.comclass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 62910458Sandreas.hansson@arm.comclass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 63010458Sandreas.hansson@arm.comclass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 63110458Sandreas.hansson@arm.comclass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 63210458Sandreas.hansson@arm.comclass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 63310458Sandreas.hansson@arm.comclass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 63410458Sandreas.hansson@arm.comclass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 63510458Sandreas.hansson@arm.com 6363101Sstever@eecs.umich.educlass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 6373101Sstever@eecs.umich.educlass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 63810267SGeoffrey.Blake@arm.comclass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 6393101Sstever@eecs.umich.educlass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 6403101Sstever@eecs.umich.edu 6413101Sstever@eecs.umich.educlass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 6423101Sstever@eecs.umich.edu 6433101Sstever@eecs.umich.educlass Cycles(CheckedInt): 6443101Sstever@eecs.umich.edu cxx_type = 'Cycles' 6453102Sstever@eecs.umich.edu size = 64 6463101Sstever@eecs.umich.edu unsigned = True 6473101Sstever@eecs.umich.edu 6483101Sstever@eecs.umich.edu def getValue(self): 6494168Sbinkertn@umich.edu from _m5.core import Cycles 65010267SGeoffrey.Blake@arm.com return Cycles(self.value) 6513101Sstever@eecs.umich.edu 6523101Sstever@eecs.umich.edu @classmethod 6533101Sstever@eecs.umich.edu def cxx_ini_predecls(cls, code): 6543101Sstever@eecs.umich.edu # Assume that base/str.hh will be included anyway 6553101Sstever@eecs.umich.edu # code('#include "base/str.hh"') 6563101Sstever@eecs.umich.edu pass 6573102Sstever@eecs.umich.edu 6583101Sstever@eecs.umich.edu @classmethod 6593101Sstever@eecs.umich.edu def cxx_ini_parse(cls, code, src, dest, ret): 6603101Sstever@eecs.umich.edu code('uint64_t _temp;') 6613101Sstever@eecs.umich.edu code('bool _ret = to_number(%s, _temp);' % src) 6623101Sstever@eecs.umich.edu code('if (_ret)') 6633101Sstever@eecs.umich.edu code(' %s = Cycles(_temp);' % dest) 6643101Sstever@eecs.umich.edu code('%s _ret;' % ret) 6653101Sstever@eecs.umich.edu 6663101Sstever@eecs.umich.educlass Float(ParamValue, float): 6673101Sstever@eecs.umich.edu cxx_type = 'double' 6683101Sstever@eecs.umich.edu cmd_line_settable = True 66910317Smitch.hayenga@arm.com 67010317Smitch.hayenga@arm.com def __init__(self, value): 67110317Smitch.hayenga@arm.com if isinstance(value, (int, long, float, NumericParamValue, Float, str)): 67210317Smitch.hayenga@arm.com self.value = float(value) 67310317Smitch.hayenga@arm.com else: 6743102Sstever@eecs.umich.edu raise TypeError("Can't convert object of type %s to Float" \ 67510317Smitch.hayenga@arm.com % type(value).__name__) 67610317Smitch.hayenga@arm.com 67710317Smitch.hayenga@arm.com def __call__(self, value): 67810317Smitch.hayenga@arm.com self.__init__(value) 67910317Smitch.hayenga@arm.com return value 6803101Sstever@eecs.umich.edu 6813584Ssaidi@eecs.umich.edu def getValue(self): 6823584Ssaidi@eecs.umich.edu return float(self.value) 6833584Ssaidi@eecs.umich.edu 6843584Ssaidi@eecs.umich.edu def config_value(self): 6853584Ssaidi@eecs.umich.edu return self 68610267SGeoffrey.Blake@arm.com 68710267SGeoffrey.Blake@arm.com @classmethod 68810267SGeoffrey.Blake@arm.com def cxx_ini_predecls(cls, code): 68910267SGeoffrey.Blake@arm.com code('#include <sstream>') 69010267SGeoffrey.Blake@arm.com 69110267SGeoffrey.Blake@arm.com @classmethod 6923101Sstever@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 6939232Sandreas.hansson@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 6949235Sandreas.hansson@arm.com 6953101Sstever@eecs.umich.educlass MemorySize(CheckedInt): 6963101Sstever@eecs.umich.edu cxx_type = 'uint64_t' 69710676Sandreas.hansson@arm.com ex_str = '512MB' 6989411Sandreas.hansson@arm.com size = 64 69910676Sandreas.hansson@arm.com unsigned = True 7009411Sandreas.hansson@arm.com def __init__(self, value): 7019411Sandreas.hansson@arm.com if isinstance(value, MemorySize): 7029411Sandreas.hansson@arm.com self.value = value.value 7033101Sstever@eecs.umich.edu else: 7049411Sandreas.hansson@arm.com self.value = convert.toMemorySize(value) 7059411Sandreas.hansson@arm.com self._check() 7069411Sandreas.hansson@arm.com 7073101Sstever@eecs.umich.educlass MemorySize32(CheckedInt): 7089232Sandreas.hansson@arm.com cxx_type = 'uint32_t' 7093101Sstever@eecs.umich.edu ex_str = '512MB' 7109232Sandreas.hansson@arm.com size = 32 7113101Sstever@eecs.umich.edu unsigned = True 7123101Sstever@eecs.umich.edu def __init__(self, value): 7133101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 7149411Sandreas.hansson@arm.com self.value = value.value 7159411Sandreas.hansson@arm.com else: 7169411Sandreas.hansson@arm.com self.value = convert.toMemorySize(value) 71710676Sandreas.hansson@arm.com self._check() 71810676Sandreas.hansson@arm.com 7199411Sandreas.hansson@arm.comclass Addr(CheckedInt): 7209411Sandreas.hansson@arm.com cxx_type = 'Addr' 7219411Sandreas.hansson@arm.com size = 64 7229411Sandreas.hansson@arm.com unsigned = True 7239411Sandreas.hansson@arm.com def __init__(self, value): 7243101Sstever@eecs.umich.edu if isinstance(value, Addr): 7259232Sandreas.hansson@arm.com self.value = value.value 7263101Sstever@eecs.umich.edu else: 7273101Sstever@eecs.umich.edu try: 7283101Sstever@eecs.umich.edu # Often addresses are referred to with sizes. Ex: A device 7293101Sstever@eecs.umich.edu # base address is at "512MB". Use toMemorySize() to convert 7309232Sandreas.hansson@arm.com # these into addresses. If the address is not specified with a 7313101Sstever@eecs.umich.edu # "size", an exception will occur and numeric translation will 7325219Ssaidi@eecs.umich.edu # proceed below. 7339232Sandreas.hansson@arm.com self.value = convert.toMemorySize(value) 7349232Sandreas.hansson@arm.com except (TypeError, ValueError): 7353101Sstever@eecs.umich.edu # Convert number to string and use long() to do automatic 7369232Sandreas.hansson@arm.com # base conversion (requires base=0 for auto-conversion) 7379232Sandreas.hansson@arm.com self.value = long(str(value), base=0) 7383101Sstever@eecs.umich.edu 7393101Sstever@eecs.umich.edu self._check() 7409232Sandreas.hansson@arm.com def __add__(self, other): 7419232Sandreas.hansson@arm.com if isinstance(other, Addr): 7423101Sstever@eecs.umich.edu return self.value + other.value 7433101Sstever@eecs.umich.edu else: 7443101Sstever@eecs.umich.edu return self.value + other 7453101Sstever@eecs.umich.edu def pretty_print(self, value): 7469232Sandreas.hansson@arm.com try: 7473101Sstever@eecs.umich.edu val = convert.toMemorySize(value) 7483101Sstever@eecs.umich.edu except TypeError: 74911620SMatthew.Poremba@amd.com val = long(value) 75011620SMatthew.Poremba@amd.com return "0x%x" % long(val) 75111620SMatthew.Poremba@amd.com 7529232Sandreas.hansson@arm.comclass AddrRange(ParamValue): 7539232Sandreas.hansson@arm.com cxx_type = 'AddrRange' 7549411Sandreas.hansson@arm.com 7559411Sandreas.hansson@arm.com def __init__(self, *args, **kwargs): 7563101Sstever@eecs.umich.edu # Disable interleaving and hashing by default 7577673Snate@binkert.org self.intlvHighBit = 0 7587673Snate@binkert.org self.xorHighBit = 0 7599232Sandreas.hansson@arm.com self.intlvBits = 0 7609235Sandreas.hansson@arm.com self.intlvMatch = 0 7617675Snate@binkert.org 7627675Snate@binkert.org def handle_kwargs(self, kwargs): 76311988Sandreas.sandberg@arm.com # An address range needs to have an upper limit, specified 76411988Sandreas.sandberg@arm.com # either explicitly with an end, or as an offset using the 76511988Sandreas.sandberg@arm.com # size keyword. 76611988Sandreas.sandberg@arm.com if 'end' in kwargs: 76711988Sandreas.sandberg@arm.com self.end = Addr(kwargs.pop('end')) 76810458Sandreas.hansson@arm.com elif 'size' in kwargs: 76910458Sandreas.hansson@arm.com self.end = self.start + Addr(kwargs.pop('size')) - 1 77010458Sandreas.hansson@arm.com else: 77110458Sandreas.hansson@arm.com raise TypeError("Either end or size must be specified") 77210458Sandreas.hansson@arm.com 77311620SMatthew.Poremba@amd.com # Now on to the optional bit 77411620SMatthew.Poremba@amd.com if 'intlvHighBit' in kwargs: 77510458Sandreas.hansson@arm.com self.intlvHighBit = int(kwargs.pop('intlvHighBit')) 77610458Sandreas.hansson@arm.com if 'xorHighBit' in kwargs: 77710458Sandreas.hansson@arm.com self.xorHighBit = int(kwargs.pop('xorHighBit')) 77810458Sandreas.hansson@arm.com if 'intlvBits' in kwargs: 77910458Sandreas.hansson@arm.com self.intlvBits = int(kwargs.pop('intlvBits')) 78011620SMatthew.Poremba@amd.com if 'intlvMatch' in kwargs: 78111620SMatthew.Poremba@amd.com self.intlvMatch = int(kwargs.pop('intlvMatch')) 78211620SMatthew.Poremba@amd.com 78311620SMatthew.Poremba@amd.com if len(args) == 0: 78411620SMatthew.Poremba@amd.com self.start = Addr(kwargs.pop('start')) 78511620SMatthew.Poremba@amd.com handle_kwargs(self, kwargs) 78611620SMatthew.Poremba@amd.com 78711620SMatthew.Poremba@amd.com elif len(args) == 1: 78811620SMatthew.Poremba@amd.com if kwargs: 78911620SMatthew.Poremba@amd.com self.start = Addr(args[0]) 79010458Sandreas.hansson@arm.com handle_kwargs(self, kwargs) 79110458Sandreas.hansson@arm.com elif isinstance(args[0], (list, tuple)): 79210458Sandreas.hansson@arm.com self.start = Addr(args[0][0]) 79311620SMatthew.Poremba@amd.com self.end = Addr(args[0][1]) 79411620SMatthew.Poremba@amd.com else: 79510458Sandreas.hansson@arm.com self.start = Addr(0) 79610458Sandreas.hansson@arm.com self.end = Addr(args[0]) - 1 7974762Snate@binkert.org 79811991Sandreas.sandberg@arm.com elif len(args) == 2: 79911802Sandreas.sandberg@arm.com self.start = Addr(args[0]) 8004762Snate@binkert.org self.end = Addr(args[1]) 8019411Sandreas.hansson@arm.com else: 80210676Sandreas.hansson@arm.com raise TypeError("Too many arguments specified") 80310676Sandreas.hansson@arm.com 8043101Sstever@eecs.umich.edu if kwargs: 8053101Sstever@eecs.umich.edu raise TypeError("Too many keywords: %s" % list(kwargs.keys())) 8063101Sstever@eecs.umich.edu 8073101Sstever@eecs.umich.edu def __str__(self): 8083101Sstever@eecs.umich.edu return '%s:%s:%s:%s:%s:%s' \ 8093101Sstever@eecs.umich.edu % (self.start, self.end, self.intlvHighBit, self.xorHighBit,\ 81010267SGeoffrey.Blake@arm.com self.intlvBits, self.intlvMatch) 81110267SGeoffrey.Blake@arm.com 8123101Sstever@eecs.umich.edu def size(self): 8133101Sstever@eecs.umich.edu # Divide the size by the size of the interleaving slice 8143102Sstever@eecs.umich.edu return (long(self.end) - long(self.start) + 1) >> self.intlvBits 8153101Sstever@eecs.umich.edu 8163101Sstever@eecs.umich.edu @classmethod 8173101Sstever@eecs.umich.edu def cxx_predecls(cls, code): 81810267SGeoffrey.Blake@arm.com Addr.cxx_predecls(code) 81910267SGeoffrey.Blake@arm.com code('#include "base/addr_range.hh"') 82010267SGeoffrey.Blake@arm.com 82110267SGeoffrey.Blake@arm.com @classmethod 8224762Snate@binkert.org def pybind_predecls(cls, code): 8234762Snate@binkert.org Addr.pybind_predecls(code) 8244762Snate@binkert.org code('#include "base/addr_range.hh"') 8253101Sstever@eecs.umich.edu 8263101Sstever@eecs.umich.edu @classmethod 8273101Sstever@eecs.umich.edu def cxx_ini_predecls(cls, code): 8288934SBrad.Beckmann@amd.com code('#include <sstream>') 8298934SBrad.Beckmann@amd.com 8308934SBrad.Beckmann@amd.com @classmethod 8318934SBrad.Beckmann@amd.com def cxx_ini_parse(cls, code, src, dest, ret): 8328934SBrad.Beckmann@amd.com code('uint64_t _start, _end, _intlvHighBit = 0, _xorHighBit = 0;') 8333101Sstever@eecs.umich.edu code('uint64_t _intlvBits = 0, _intlvMatch = 0;') 8343101Sstever@eecs.umich.edu code('char _sep;') 8353101Sstever@eecs.umich.edu code('std::istringstream _stream(${src});') 8363101Sstever@eecs.umich.edu code('_stream >> _start;') 8373101Sstever@eecs.umich.edu code('_stream.get(_sep);') 83810380SAndrew.Bardsley@arm.com code('_stream >> _end;') 83910380SAndrew.Bardsley@arm.com code('if (!_stream.fail() && !_stream.eof()) {') 84010380SAndrew.Bardsley@arm.com code(' _stream.get(_sep);') 84110458Sandreas.hansson@arm.com code(' _stream >> _intlvHighBit;') 84210458Sandreas.hansson@arm.com code(' _stream.get(_sep);') 84310458Sandreas.hansson@arm.com code(' _stream >> _xorHighBit;') 84410458Sandreas.hansson@arm.com code(' _stream.get(_sep);') 84510458Sandreas.hansson@arm.com code(' _stream >> _intlvBits;') 84610458Sandreas.hansson@arm.com code(' _stream.get(_sep);') 84710458Sandreas.hansson@arm.com code(' _stream >> _intlvMatch;') 84810458Sandreas.hansson@arm.com code('}') 84910458Sandreas.hansson@arm.com code('bool _ret = !_stream.fail() &&' 85010458Sandreas.hansson@arm.com '_stream.eof() && _sep == \':\';') 8513101Sstever@eecs.umich.edu code('if (_ret)') 8523101Sstever@eecs.umich.edu code(' ${dest} = AddrRange(_start, _end, _intlvHighBit, \ 8533101Sstever@eecs.umich.edu _xorHighBit, _intlvBits, _intlvMatch);') 8543101Sstever@eecs.umich.edu code('${ret} _ret;') 8553101Sstever@eecs.umich.edu 8563101Sstever@eecs.umich.edu def getValue(self): 8573101Sstever@eecs.umich.edu # Go from the Python class to the wrapped C++ class 8583101Sstever@eecs.umich.edu from _m5.range import AddrRange 8593101Sstever@eecs.umich.edu 8603101Sstever@eecs.umich.edu return AddrRange(long(self.start), long(self.end), 8613101Sstever@eecs.umich.edu int(self.intlvHighBit), int(self.xorHighBit), 8623101Sstever@eecs.umich.edu int(self.intlvBits), int(self.intlvMatch)) 8634380Sbinkertn@umich.edu 8644380Sbinkertn@umich.edu# Boolean parameter type. Python doesn't let you subclass bool, since 8654380Sbinkertn@umich.edu# it doesn't want to let you create multiple instances of True and 8663101Sstever@eecs.umich.edu# False. Thus this is a little more complicated than String. 8674380Sbinkertn@umich.educlass Bool(ParamValue): 8684380Sbinkertn@umich.edu cxx_type = 'bool' 8694380Sbinkertn@umich.edu cmd_line_settable = True 8703101Sstever@eecs.umich.edu 8713101Sstever@eecs.umich.edu def __init__(self, value): 8723101Sstever@eecs.umich.edu try: 87310267SGeoffrey.Blake@arm.com self.value = convert.toBool(value) 87410267SGeoffrey.Blake@arm.com except TypeError: 8757673Snate@binkert.org self.value = bool(value) 8767673Snate@binkert.org 8777673Snate@binkert.org def __call__(self, value): 8787673Snate@binkert.org self.__init__(value) 8797673Snate@binkert.org return value 8803101Sstever@eecs.umich.edu 8813101Sstever@eecs.umich.edu def getValue(self): 8823101Sstever@eecs.umich.edu return bool(self.value) 8833101Sstever@eecs.umich.edu 8843101Sstever@eecs.umich.edu def __str__(self): 8853101Sstever@eecs.umich.edu return str(self.value) 8863101Sstever@eecs.umich.edu 8873101Sstever@eecs.umich.edu # implement truth value testing for Bool parameters so that these params 8883101Sstever@eecs.umich.edu # evaluate correctly during the python configuration phase 8893101Sstever@eecs.umich.edu def __bool__(self): 8903101Sstever@eecs.umich.edu return bool(self.value) 8913101Sstever@eecs.umich.edu 8923101Sstever@eecs.umich.edu # Python 2.7 uses __nonzero__ instead of __bool__ 8939941SGeoffrey.Blake@arm.com __nonzero__ = __bool__ 8943101Sstever@eecs.umich.edu 8953101Sstever@eecs.umich.edu def ini_str(self): 8963101Sstever@eecs.umich.edu if self.value: 8973101Sstever@eecs.umich.edu return 'true' 89810267SGeoffrey.Blake@arm.com return 'false' 89910267SGeoffrey.Blake@arm.com 90010267SGeoffrey.Blake@arm.com def config_value(self): 90110267SGeoffrey.Blake@arm.com return self.value 9023101Sstever@eecs.umich.edu 9033101Sstever@eecs.umich.edu @classmethod 9044380Sbinkertn@umich.edu def cxx_ini_predecls(cls, code): 9053101Sstever@eecs.umich.edu # Assume that base/str.hh will be included anyway 9063101Sstever@eecs.umich.edu # code('#include "base/str.hh"') 9074762Snate@binkert.org pass 90811988Sandreas.sandberg@arm.com 9094762Snate@binkert.org @classmethod 9104762Snate@binkert.org def cxx_ini_parse(cls, code, src, dest, ret): 91111228SAndrew.Bardsley@arm.com code('%s to_bool(%s, %s);' % (ret, src, dest)) 91211228SAndrew.Bardsley@arm.com 91311228SAndrew.Bardsley@arm.comdef IncEthernetAddr(addr, val = 1): 9144380Sbinkertn@umich.edu bytes = [ int(x, 16) for x in addr.split(':') ] 9154380Sbinkertn@umich.edu bytes[5] += val 9163101Sstever@eecs.umich.edu for i in (5, 4, 3, 2, 1): 91710458Sandreas.hansson@arm.com val,rem = divmod(bytes[i], 256) 91810458Sandreas.hansson@arm.com bytes[i] = rem 91910458Sandreas.hansson@arm.com if val == 0: 92010458Sandreas.hansson@arm.com break 92110458Sandreas.hansson@arm.com bytes[i - 1] += val 9227777Sgblack@eecs.umich.edu assert(bytes[0] <= 255) 9237777Sgblack@eecs.umich.edu return ':'.join(map(lambda x: '%02x' % x, bytes)) 9247777Sgblack@eecs.umich.edu 9257777Sgblack@eecs.umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 92610267SGeoffrey.Blake@arm.comdef NextEthernetAddr(): 92710267SGeoffrey.Blake@arm.com global _NextEthernetAddr 9287777Sgblack@eecs.umich.edu 9297777Sgblack@eecs.umich.edu value = _NextEthernetAddr 9307777Sgblack@eecs.umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 9317777Sgblack@eecs.umich.edu return value 9327777Sgblack@eecs.umich.edu 9337777Sgblack@eecs.umich.educlass EthernetAddr(ParamValue): 9347777Sgblack@eecs.umich.edu cxx_type = 'Net::EthAddr' 9357777Sgblack@eecs.umich.edu ex_str = "00:90:00:00:00:01" 9367777Sgblack@eecs.umich.edu cmd_line_settable = True 9377777Sgblack@eecs.umich.edu 9387777Sgblack@eecs.umich.edu @classmethod 9397777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 9407777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 9417777Sgblack@eecs.umich.edu 9427777Sgblack@eecs.umich.edu def __init__(self, value): 94310267SGeoffrey.Blake@arm.com if value == NextEthernetAddr: 94410267SGeoffrey.Blake@arm.com self.value = value 94510267SGeoffrey.Blake@arm.com return 94610267SGeoffrey.Blake@arm.com 9478579Ssteve.reinhardt@amd.com if not isinstance(value, str): 9488579Ssteve.reinhardt@amd.com raise TypeError("expected an ethernet address and didn't get one") 9498579Ssteve.reinhardt@amd.com 9508579Ssteve.reinhardt@amd.com bytes = value.split(':') 9518579Ssteve.reinhardt@amd.com if len(bytes) != 6: 9528579Ssteve.reinhardt@amd.com raise TypeError('invalid ethernet address %s' % value) 9538579Ssteve.reinhardt@amd.com 9548579Ssteve.reinhardt@amd.com for byte in bytes: 9558579Ssteve.reinhardt@amd.com if not 0 <= int(byte, base=16) <= 0xff: 9568579Ssteve.reinhardt@amd.com raise TypeError('invalid ethernet address %s' % value) 9578579Ssteve.reinhardt@amd.com 9588579Ssteve.reinhardt@amd.com self.value = value 9598579Ssteve.reinhardt@amd.com 9608579Ssteve.reinhardt@amd.com def __call__(self, value): 9618579Ssteve.reinhardt@amd.com self.__init__(value) 9628579Ssteve.reinhardt@amd.com return value 9638579Ssteve.reinhardt@amd.com 9648579Ssteve.reinhardt@amd.com def unproxy(self, base): 9657777Sgblack@eecs.umich.edu if self.value == NextEthernetAddr: 9667777Sgblack@eecs.umich.edu return EthernetAddr(self.value()) 9677798Sgblack@eecs.umich.edu return self 9687777Sgblack@eecs.umich.edu 9697777Sgblack@eecs.umich.edu def getValue(self): 97011988Sandreas.sandberg@arm.com from _m5.net import EthAddr 9717777Sgblack@eecs.umich.edu return EthAddr(self.value) 9727777Sgblack@eecs.umich.edu 9737777Sgblack@eecs.umich.edu def __str__(self): 9747777Sgblack@eecs.umich.edu return self.value 9757777Sgblack@eecs.umich.edu 9767777Sgblack@eecs.umich.edu def ini_str(self): 9777777Sgblack@eecs.umich.edu return self.value 97810267SGeoffrey.Blake@arm.com 97910267SGeoffrey.Blake@arm.com @classmethod 9807777Sgblack@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 9817777Sgblack@eecs.umich.edu code('%s = Net::EthAddr(%s);' % (dest, src)) 9827777Sgblack@eecs.umich.edu code('%s true;' % ret) 9837777Sgblack@eecs.umich.edu 9847777Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of 9857777Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP. 9867777Sgblack@eecs.umich.educlass IpAddress(ParamValue): 9877777Sgblack@eecs.umich.edu cxx_type = 'Net::IpAddress' 9887777Sgblack@eecs.umich.edu ex_str = "127.0.0.1" 9897777Sgblack@eecs.umich.edu cmd_line_settable = True 9907777Sgblack@eecs.umich.edu 9917777Sgblack@eecs.umich.edu @classmethod 9927777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 9937777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 9947777Sgblack@eecs.umich.edu 9957777Sgblack@eecs.umich.edu def __init__(self, value): 9967777Sgblack@eecs.umich.edu if isinstance(value, IpAddress): 9977777Sgblack@eecs.umich.edu self.ip = value.ip 9987777Sgblack@eecs.umich.edu else: 9997777Sgblack@eecs.umich.edu try: 10007777Sgblack@eecs.umich.edu self.ip = convert.toIpAddress(value) 10017777Sgblack@eecs.umich.edu except TypeError: 10027777Sgblack@eecs.umich.edu self.ip = long(value) 10037777Sgblack@eecs.umich.edu self.verifyIp() 10047777Sgblack@eecs.umich.edu 10057777Sgblack@eecs.umich.edu def __call__(self, value): 10067777Sgblack@eecs.umich.edu self.__init__(value) 10077777Sgblack@eecs.umich.edu return value 10087777Sgblack@eecs.umich.edu 10097777Sgblack@eecs.umich.edu def __str__(self): 10107777Sgblack@eecs.umich.edu tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)] 10117777Sgblack@eecs.umich.edu return '%d.%d.%d.%d' % tuple(tup) 10127777Sgblack@eecs.umich.edu 10137777Sgblack@eecs.umich.edu def __eq__(self, other): 10147777Sgblack@eecs.umich.edu if isinstance(other, IpAddress): 10157777Sgblack@eecs.umich.edu return self.ip == other.ip 10167777Sgblack@eecs.umich.edu elif isinstance(other, str): 10177777Sgblack@eecs.umich.edu try: 10187777Sgblack@eecs.umich.edu return self.ip == convert.toIpAddress(other) 10197777Sgblack@eecs.umich.edu except: 10207777Sgblack@eecs.umich.edu return False 102110267SGeoffrey.Blake@arm.com else: 102210267SGeoffrey.Blake@arm.com return self.ip == other 102310267SGeoffrey.Blake@arm.com 102410267SGeoffrey.Blake@arm.com def __ne__(self, other): 10258579Ssteve.reinhardt@amd.com return not (self == other) 10268579Ssteve.reinhardt@amd.com 10278579Ssteve.reinhardt@amd.com def verifyIp(self): 10288579Ssteve.reinhardt@amd.com if self.ip < 0 or self.ip >= (1 << 32): 10298579Ssteve.reinhardt@amd.com raise TypeError("invalid ip address %#08x" % self.ip) 10308579Ssteve.reinhardt@amd.com 10318579Ssteve.reinhardt@amd.com def getValue(self): 10328579Ssteve.reinhardt@amd.com from _m5.net import IpAddress 10338579Ssteve.reinhardt@amd.com return IpAddress(self.ip) 10348579Ssteve.reinhardt@amd.com 10358579Ssteve.reinhardt@amd.com# When initializing an IpNetmask, pass in an existing IpNetmask, a string of 10368579Ssteve.reinhardt@amd.com# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as 10378579Ssteve.reinhardt@amd.com# positional or keyword arguments. 10388579Ssteve.reinhardt@amd.comclass IpNetmask(IpAddress): 10397777Sgblack@eecs.umich.edu cxx_type = 'Net::IpNetmask' 10407777Sgblack@eecs.umich.edu ex_str = "127.0.0.0/24" 10417777Sgblack@eecs.umich.edu cmd_line_settable = True 10427777Sgblack@eecs.umich.edu 10437777Sgblack@eecs.umich.edu @classmethod 10447777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 104511988Sandreas.sandberg@arm.com code('#include "base/inet.hh"') 10467777Sgblack@eecs.umich.edu 10477777Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 10487777Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 10497777Sgblack@eecs.umich.edu if key in kwargs: 10507777Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 10517777Sgblack@eecs.umich.edu elif elseVal: 105210267SGeoffrey.Blake@arm.com setattr(self, key, elseVal) 105310267SGeoffrey.Blake@arm.com else: 10547777Sgblack@eecs.umich.edu raise TypeError("No value set for %s" % key) 10557777Sgblack@eecs.umich.edu 10567777Sgblack@eecs.umich.edu if len(args) == 0: 10577777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip') 10587777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask') 10597777Sgblack@eecs.umich.edu 10607777Sgblack@eecs.umich.edu elif len(args) == 1: 10617777Sgblack@eecs.umich.edu if kwargs: 10627777Sgblack@eecs.umich.edu if not 'ip' in kwargs and not 'netmask' in kwargs: 10637777Sgblack@eecs.umich.edu raise TypeError("Invalid arguments") 10647777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 10657777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask', args[0]) 10667777Sgblack@eecs.umich.edu elif isinstance(args[0], IpNetmask): 10677777Sgblack@eecs.umich.edu self.ip = args[0].ip 10687777Sgblack@eecs.umich.edu self.netmask = args[0].netmask 10697777Sgblack@eecs.umich.edu else: 10707777Sgblack@eecs.umich.edu (self.ip, self.netmask) = convert.toIpNetmask(args[0]) 10717777Sgblack@eecs.umich.edu 10727777Sgblack@eecs.umich.edu elif len(args) == 2: 10737777Sgblack@eecs.umich.edu self.ip = args[0] 10747777Sgblack@eecs.umich.edu self.netmask = args[1] 10757777Sgblack@eecs.umich.edu else: 10767777Sgblack@eecs.umich.edu raise TypeError("Too many arguments specified") 10777777Sgblack@eecs.umich.edu 10787777Sgblack@eecs.umich.edu if kwargs: 10797777Sgblack@eecs.umich.edu raise TypeError("Too many keywords: %s" % list(kwargs.keys())) 10807777Sgblack@eecs.umich.edu 10817777Sgblack@eecs.umich.edu self.verify() 10827777Sgblack@eecs.umich.edu 10837777Sgblack@eecs.umich.edu def __call__(self, value): 10847777Sgblack@eecs.umich.edu self.__init__(value) 10857777Sgblack@eecs.umich.edu return value 10867777Sgblack@eecs.umich.edu 10877777Sgblack@eecs.umich.edu def __str__(self): 10887777Sgblack@eecs.umich.edu return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask) 10897777Sgblack@eecs.umich.edu 10907777Sgblack@eecs.umich.edu def __eq__(self, other): 10917777Sgblack@eecs.umich.edu if isinstance(other, IpNetmask): 10927777Sgblack@eecs.umich.edu return self.ip == other.ip and self.netmask == other.netmask 10937777Sgblack@eecs.umich.edu elif isinstance(other, str): 10947777Sgblack@eecs.umich.edu try: 109510267SGeoffrey.Blake@arm.com return (self.ip, self.netmask) == convert.toIpNetmask(other) 109610267SGeoffrey.Blake@arm.com except: 109710267SGeoffrey.Blake@arm.com return False 109810267SGeoffrey.Blake@arm.com else: 10998579Ssteve.reinhardt@amd.com return False 11008579Ssteve.reinhardt@amd.com 11018579Ssteve.reinhardt@amd.com def verify(self): 11028579Ssteve.reinhardt@amd.com self.verifyIp() 11038579Ssteve.reinhardt@amd.com if self.netmask < 0 or self.netmask > 32: 11048579Ssteve.reinhardt@amd.com raise TypeError("invalid netmask %d" % netmask) 11058579Ssteve.reinhardt@amd.com 11068579Ssteve.reinhardt@amd.com def getValue(self): 11078579Ssteve.reinhardt@amd.com from _m5.net import IpNetmask 11088579Ssteve.reinhardt@amd.com return IpNetmask(self.ip, self.netmask) 11098579Ssteve.reinhardt@amd.com 11108579Ssteve.reinhardt@amd.com# When initializing an IpWithPort, pass in an existing IpWithPort, a string of 11118579Ssteve.reinhardt@amd.com# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments. 11128579Ssteve.reinhardt@amd.comclass IpWithPort(IpAddress): 11137777Sgblack@eecs.umich.edu cxx_type = 'Net::IpWithPort' 11147777Sgblack@eecs.umich.edu ex_str = "127.0.0.1:80" 11157777Sgblack@eecs.umich.edu cmd_line_settable = True 11167777Sgblack@eecs.umich.edu 11177777Sgblack@eecs.umich.edu @classmethod 11187777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 111911988Sandreas.sandberg@arm.com code('#include "base/inet.hh"') 11207777Sgblack@eecs.umich.edu 11217777Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 11223932Sbinkertn@umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 112310380SAndrew.Bardsley@arm.com if key in kwargs: 11243932Sbinkertn@umich.edu setattr(self, key, kwargs.pop(key)) 11253932Sbinkertn@umich.edu elif elseVal: 11263932Sbinkertn@umich.edu setattr(self, key, elseVal) 11273932Sbinkertn@umich.edu else: 11283932Sbinkertn@umich.edu raise TypeError("No value set for %s" % key) 11293932Sbinkertn@umich.edu 11303932Sbinkertn@umich.edu if len(args) == 0: 11313932Sbinkertn@umich.edu handle_kwarg(self, kwargs, 'ip') 11323932Sbinkertn@umich.edu handle_kwarg(self, kwargs, 'port') 11333932Sbinkertn@umich.edu 11343932Sbinkertn@umich.edu elif len(args) == 1: 11353885Sbinkertn@umich.edu if kwargs: 11363932Sbinkertn@umich.edu if not 'ip' in kwargs and not 'port' in kwargs: 11373932Sbinkertn@umich.edu raise TypeError("Invalid arguments") 11383885Sbinkertn@umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 11393932Sbinkertn@umich.edu handle_kwarg(self, kwargs, 'port', args[0]) 11403932Sbinkertn@umich.edu elif isinstance(args[0], IpWithPort): 11413932Sbinkertn@umich.edu self.ip = args[0].ip 11423932Sbinkertn@umich.edu self.port = args[0].port 11433932Sbinkertn@umich.edu else: 11443932Sbinkertn@umich.edu (self.ip, self.port) = convert.toIpWithPort(args[0]) 11453932Sbinkertn@umich.edu 11463932Sbinkertn@umich.edu elif len(args) == 2: 11473932Sbinkertn@umich.edu self.ip = args[0] 11483932Sbinkertn@umich.edu self.port = args[1] 11493932Sbinkertn@umich.edu else: 11503932Sbinkertn@umich.edu raise TypeError("Too many arguments specified") 11513932Sbinkertn@umich.edu 11523932Sbinkertn@umich.edu if kwargs: 11533932Sbinkertn@umich.edu raise TypeError("Too many keywords: %s" % list(kwargs.keys())) 11543932Sbinkertn@umich.edu 11553932Sbinkertn@umich.edu self.verify() 11563932Sbinkertn@umich.edu 11573885Sbinkertn@umich.edu def __call__(self, value): 11583885Sbinkertn@umich.edu self.__init__(value) 11593885Sbinkertn@umich.edu return value 11603885Sbinkertn@umich.edu 11614762Snate@binkert.org def __str__(self): 11627673Snate@binkert.org return "%s:%d" % (super(IpWithPort, self).__str__(), self.port) 11637673Snate@binkert.org 11647673Snate@binkert.org def __eq__(self, other): 11657673Snate@binkert.org if isinstance(other, IpWithPort): 11667673Snate@binkert.org return self.ip == other.ip and self.port == other.port 11673885Sbinkertn@umich.edu elif isinstance(other, str): 11683932Sbinkertn@umich.edu try: 11693885Sbinkertn@umich.edu return (self.ip, self.port) == convert.toIpWithPort(other) 117010267SGeoffrey.Blake@arm.com except: 117110267SGeoffrey.Blake@arm.com return False 117210267SGeoffrey.Blake@arm.com else: 117310267SGeoffrey.Blake@arm.com return False 11744762Snate@binkert.org 117511988Sandreas.sandberg@arm.com def verify(self): 117611988Sandreas.sandberg@arm.com self.verifyIp() 11774762Snate@binkert.org if self.port < 0 or self.port > 0xffff: 117811988Sandreas.sandberg@arm.com raise TypeError("invalid port %d" % self.port) 11794762Snate@binkert.org 11803885Sbinkertn@umich.edu def getValue(self): 11814762Snate@binkert.org from _m5.net import IpWithPort 11823885Sbinkertn@umich.edu return IpWithPort(self.ip, self.port) 11833885Sbinkertn@umich.edu 11843932Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 11853885Sbinkertn@umich.edu "%a %b %d %H:%M:%S %Y", 11868664SAli.Saidi@ARM.com "%Y/%m/%d %H:%M:%S", 118710380SAndrew.Bardsley@arm.com "%Y/%m/%d %H:%M", 11888664SAli.Saidi@ARM.com "%Y/%m/%d", 11898664SAli.Saidi@ARM.com "%m/%d/%Y %H:%M:%S", 119010458Sandreas.hansson@arm.com "%m/%d/%Y %H:%M", 119110458Sandreas.hansson@arm.com "%m/%d/%Y", 119210458Sandreas.hansson@arm.com "%m/%d/%y %H:%M:%S", 119310458Sandreas.hansson@arm.com "%m/%d/%y %H:%M", 119410458Sandreas.hansson@arm.com "%m/%d/%y"] 119510458Sandreas.hansson@arm.com 119610458Sandreas.hansson@arm.com 119710458Sandreas.hansson@arm.comdef parse_time(value): 119810458Sandreas.hansson@arm.com from time import gmtime, strptime, struct_time, time 119910458Sandreas.hansson@arm.com from datetime import datetime, date 12003101Sstever@eecs.umich.edu 12013101Sstever@eecs.umich.edu if isinstance(value, struct_time): 12023101Sstever@eecs.umich.edu return value 12033101Sstever@eecs.umich.edu 12043101Sstever@eecs.umich.edu if isinstance(value, (int, long)): 12053101Sstever@eecs.umich.edu return gmtime(value) 12063101Sstever@eecs.umich.edu 12073101Sstever@eecs.umich.edu if isinstance(value, (datetime, date)): 12083101Sstever@eecs.umich.edu return value.timetuple() 12093101Sstever@eecs.umich.edu 12103101Sstever@eecs.umich.edu if isinstance(value, str): 12113101Sstever@eecs.umich.edu if value in ('Now', 'Today'): 12123101Sstever@eecs.umich.edu return time.gmtime(time.time()) 12133101Sstever@eecs.umich.edu 12144762Snate@binkert.org for format in time_formats: 12153101Sstever@eecs.umich.edu try: 12165033Smilesck@eecs.umich.edu return strptime(value, format) 12174762Snate@binkert.org except ValueError: 12184762Snate@binkert.org pass 12194762Snate@binkert.org 12204762Snate@binkert.org raise ValueError("Could not parse '%s' as a time" % value) 12214762Snate@binkert.org 12224762Snate@binkert.orgclass Time(ParamValue): 12234762Snate@binkert.org cxx_type = 'tm' 12243101Sstever@eecs.umich.edu 12253101Sstever@eecs.umich.edu @classmethod 12263101Sstever@eecs.umich.edu def cxx_predecls(cls, code): 12273101Sstever@eecs.umich.edu code('#include <time.h>') 12283101Sstever@eecs.umich.edu 12293101Sstever@eecs.umich.edu def __init__(self, value): 12303101Sstever@eecs.umich.edu self.value = parse_time(value) 12313101Sstever@eecs.umich.edu 12323101Sstever@eecs.umich.edu def __call__(self, value): 12333101Sstever@eecs.umich.edu self.__init__(value) 12343101Sstever@eecs.umich.edu return value 12353101Sstever@eecs.umich.edu 12363101Sstever@eecs.umich.edu def getValue(self): 12373101Sstever@eecs.umich.edu from _m5.core import tm 12383101Sstever@eecs.umich.edu import calendar 12393101Sstever@eecs.umich.edu 12403101Sstever@eecs.umich.edu return tm.gmtime(calendar.timegm(self.value)) 12413101Sstever@eecs.umich.edu 12423101Sstever@eecs.umich.edu def __str__(self): 12433101Sstever@eecs.umich.edu return time.asctime(self.value) 12444762Snate@binkert.org 12453101Sstever@eecs.umich.edu def ini_str(self): 12463101Sstever@eecs.umich.edu return str(self) 12473101Sstever@eecs.umich.edu 12483101Sstever@eecs.umich.edu def get_config_as_dict(self): 12493101Sstever@eecs.umich.edu assert false 12503101Sstever@eecs.umich.edu return str(self) 12517673Snate@binkert.org 125210201SAndrew.Bardsley@arm.com @classmethod 125310201SAndrew.Bardsley@arm.com def cxx_ini_predecls(cls, code): 125410201SAndrew.Bardsley@arm.com code('#include <time.h>') 125510201SAndrew.Bardsley@arm.com 125610201SAndrew.Bardsley@arm.com @classmethod 12577673Snate@binkert.org def cxx_ini_parse(cls, code, src, dest, ret): 125810201SAndrew.Bardsley@arm.com code('char *_parse_ret = strptime((${src}).c_str(),') 125910201SAndrew.Bardsley@arm.com code(' "%a %b %d %H:%M:%S %Y", &(${dest}));') 12607673Snate@binkert.org code('${ret} _parse_ret && *_parse_ret == \'\\0\';'); 126110201SAndrew.Bardsley@arm.com 12627673Snate@binkert.org# Enumerated types are a little more complex. The user specifies the 12637673Snate@binkert.org# type as Enum(foo) where foo is either a list or dictionary of 12647673Snate@binkert.org# alternatives (typically strings, but not necessarily so). (In the 12654762Snate@binkert.org# long run, the integer value of the parameter will be the list index 12667673Snate@binkert.org# or the corresponding dictionary value. For now, since we only check 12678902Sandreas.hansson@arm.com# that the alternative is valid and then spit it into a .ini file, 12687673Snate@binkert.org# there's not much point in using the dictionary.) 126910201SAndrew.Bardsley@arm.com 12704762Snate@binkert.org# What Enum() must do is generate a new type encapsulating the 127110201SAndrew.Bardsley@arm.com# provided list/dictionary so that specific values of the parameter 127210201SAndrew.Bardsley@arm.com# can be instances of that type. We define two hidden internal 127310201SAndrew.Bardsley@arm.com# classes (_ListEnum and _DictEnum) to serve as base classes, then 127410201SAndrew.Bardsley@arm.com# derive the new type from the appropriate base class on the fly. 127510201SAndrew.Bardsley@arm.com 127610201SAndrew.Bardsley@arm.comallEnums = {} 127710201SAndrew.Bardsley@arm.com# Metaclass for Enum types 127810201SAndrew.Bardsley@arm.comclass MetaEnum(MetaParamValue): 127910201SAndrew.Bardsley@arm.com def __new__(mcls, name, bases, dict): 12807673Snate@binkert.org assert name not in allEnums 12817673Snate@binkert.org 128210201SAndrew.Bardsley@arm.com cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 128310201SAndrew.Bardsley@arm.com allEnums[name] = cls 128410201SAndrew.Bardsley@arm.com return cls 128510201SAndrew.Bardsley@arm.com 128610201SAndrew.Bardsley@arm.com def __init__(cls, name, bases, init_dict): 128710201SAndrew.Bardsley@arm.com if 'map' in init_dict: 128810201SAndrew.Bardsley@arm.com if not isinstance(cls.map, dict): 128910201SAndrew.Bardsley@arm.com raise TypeError("Enum-derived class attribute 'map' " \ 129010201SAndrew.Bardsley@arm.com "must be of type dict") 129110201SAndrew.Bardsley@arm.com # build list of value strings from map 129210201SAndrew.Bardsley@arm.com cls.vals = list(cls.map.keys()) 129310201SAndrew.Bardsley@arm.com cls.vals.sort() 129410201SAndrew.Bardsley@arm.com elif 'vals' in init_dict: 129510201SAndrew.Bardsley@arm.com if not isinstance(cls.vals, list): 129610201SAndrew.Bardsley@arm.com raise TypeError("Enum-derived class attribute 'vals' " \ 12974762Snate@binkert.org "must be of type list") 12987673Snate@binkert.org # build string->value map from vals sequence 129910201SAndrew.Bardsley@arm.com cls.map = {} 130010201SAndrew.Bardsley@arm.com for idx,val in enumerate(cls.vals): 130110201SAndrew.Bardsley@arm.com cls.map[val] = idx 130210201SAndrew.Bardsley@arm.com else: 130310201SAndrew.Bardsley@arm.com raise TypeError("Enum-derived class must define "\ 130410201SAndrew.Bardsley@arm.com "attribute 'map' or 'vals'") 13053101Sstever@eecs.umich.edu 130611988Sandreas.sandberg@arm.com if cls.is_class: 130711988Sandreas.sandberg@arm.com cls.cxx_type = '%s' % name 130811988Sandreas.sandberg@arm.com else: 130911988Sandreas.sandberg@arm.com cls.cxx_type = 'Enums::%s' % name 131011988Sandreas.sandberg@arm.com 131111988Sandreas.sandberg@arm.com super(MetaEnum, cls).__init__(name, bases, init_dict) 131211988Sandreas.sandberg@arm.com 131311988Sandreas.sandberg@arm.com # Generate C++ class declaration for this enum type. 131411988Sandreas.sandberg@arm.com # Note that we wrap the enum in a class/struct to act as a namespace, 131511988Sandreas.sandberg@arm.com # so that the enum strings can be brief w/o worrying about collisions. 131611988Sandreas.sandberg@arm.com def cxx_decl(cls, code): 131711988Sandreas.sandberg@arm.com wrapper_name = cls.wrapper_name 131811988Sandreas.sandberg@arm.com wrapper = 'struct' if cls.wrapper_is_struct else 'namespace' 131911988Sandreas.sandberg@arm.com name = cls.__name__ if cls.enum_name is None else cls.enum_name 132011988Sandreas.sandberg@arm.com idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name) 132111988Sandreas.sandberg@arm.com 132211988Sandreas.sandberg@arm.com code('''\ 132311988Sandreas.sandberg@arm.com#ifndef $idem_macro 132411988Sandreas.sandberg@arm.com#define $idem_macro 132511988Sandreas.sandberg@arm.com 132611988Sandreas.sandberg@arm.com''') 132711988Sandreas.sandberg@arm.com if cls.is_class: 132811988Sandreas.sandberg@arm.com code('''\ 132911988Sandreas.sandberg@arm.comenum class $name { 133011988Sandreas.sandberg@arm.com''') 133111988Sandreas.sandberg@arm.com else: 133211988Sandreas.sandberg@arm.com code('''\ 133311988Sandreas.sandberg@arm.com$wrapper $wrapper_name { 133411988Sandreas.sandberg@arm.com enum $name { 133511988Sandreas.sandberg@arm.com''') 133611988Sandreas.sandberg@arm.com code.indent(1) 133711988Sandreas.sandberg@arm.com code.indent(1) 133811988Sandreas.sandberg@arm.com for val in cls.vals: 133911988Sandreas.sandberg@arm.com code('$val = ${{cls.map[val]}},') 13408596Ssteve.reinhardt@amd.com code('Num_$name = ${{len(cls.vals)}}') 13413101Sstever@eecs.umich.edu code.dedent(1) 13423101Sstever@eecs.umich.edu code('};') 13433101Sstever@eecs.umich.edu 13443101Sstever@eecs.umich.edu if cls.is_class: 134510267SGeoffrey.Blake@arm.com code('''\ 13463101Sstever@eecs.umich.eduextern const char *${name}Strings[static_cast<int>(${name}::Num_${name})]; 134710201SAndrew.Bardsley@arm.com''') 134810201SAndrew.Bardsley@arm.com elif cls.wrapper_is_struct: 134910201SAndrew.Bardsley@arm.com code('static const char *${name}Strings[Num_${name}];') 135010201SAndrew.Bardsley@arm.com else: 135110201SAndrew.Bardsley@arm.com code('extern const char *${name}Strings[Num_${name}];') 135210201SAndrew.Bardsley@arm.com 135310201SAndrew.Bardsley@arm.com if not cls.is_class: 135410201SAndrew.Bardsley@arm.com code.dedent(1) 135510201SAndrew.Bardsley@arm.com code('};') 13563101Sstever@eecs.umich.edu 13573101Sstever@eecs.umich.edu code() 13583101Sstever@eecs.umich.edu code('#endif // $idem_macro') 13593101Sstever@eecs.umich.edu 13603101Sstever@eecs.umich.edu def cxx_def(cls, code): 13613101Sstever@eecs.umich.edu wrapper_name = cls.wrapper_name 136210267SGeoffrey.Blake@arm.com file_name = cls.__name__ 136310267SGeoffrey.Blake@arm.com name = cls.__name__ if cls.enum_name is None else cls.enum_name 136410267SGeoffrey.Blake@arm.com 136510267SGeoffrey.Blake@arm.com code('#include "enums/$file_name.hh"') 13667675Snate@binkert.org if cls.wrapper_is_struct: 13677675Snate@binkert.org code('const char *${wrapper_name}::${name}Strings' 13687675Snate@binkert.org '[Num_${name}] =') 13697675Snate@binkert.org else: 13707675Snate@binkert.org if cls.is_class: 137110458Sandreas.hansson@arm.com code('''\ 137210458Sandreas.hansson@arm.comconst char *${name}Strings[static_cast<int>(${name}::Num_${name})] = 137310458Sandreas.hansson@arm.com''') 137410458Sandreas.hansson@arm.com else: 137510458Sandreas.hansson@arm.com code('namespace Enums {') 137610458Sandreas.hansson@arm.com code.indent(1) 137710458Sandreas.hansson@arm.com code('const char *${name}Strings[Num_${name}] =') 137810458Sandreas.hansson@arm.com 137910458Sandreas.hansson@arm.com code('{') 138010458Sandreas.hansson@arm.com code.indent(1) 138110458Sandreas.hansson@arm.com for val in cls.vals: 138210458Sandreas.hansson@arm.com code('"$val",') 13834762Snate@binkert.org code.dedent(1) 138411988Sandreas.sandberg@arm.com code('};') 138511988Sandreas.sandberg@arm.com 138611988Sandreas.sandberg@arm.com if not cls.wrapper_is_struct and not cls.is_class: 13874762Snate@binkert.org code.dedent(1) 13883101Sstever@eecs.umich.edu code('} // namespace $wrapper_name') 13893101Sstever@eecs.umich.edu 13903101Sstever@eecs.umich.edu 13913101Sstever@eecs.umich.edu def pybind_def(cls, code): 13923101Sstever@eecs.umich.edu name = cls.__name__ 13933101Sstever@eecs.umich.edu enum_name = cls.__name__ if cls.enum_name is None else cls.enum_name 13944167Sbinkertn@umich.edu wrapper_name = enum_name if cls.is_class else cls.wrapper_name 13953101Sstever@eecs.umich.edu 139610267SGeoffrey.Blake@arm.com code('''#include "pybind11/pybind11.h" 139710267SGeoffrey.Blake@arm.com#include "pybind11/stl.h" 13987673Snate@binkert.org 13997673Snate@binkert.org#include <sim/init.hh> 14007673Snate@binkert.org 14017673Snate@binkert.orgnamespace py = pybind11; 14027673Snate@binkert.org 140310267SGeoffrey.Blake@arm.comstatic void 140410267SGeoffrey.Blake@arm.commodule_init(py::module &m_internal) 140510267SGeoffrey.Blake@arm.com{ 140610267SGeoffrey.Blake@arm.com py::module m = m_internal.def_submodule("enum_${name}"); 14074762Snate@binkert.org 14084762Snate@binkert.org''') 14094762Snate@binkert.org if cls.is_class: 141010458Sandreas.hansson@arm.com code('py::enum_<${enum_name}>(m, "enum_${name}")') 141110458Sandreas.hansson@arm.com else: 141210458Sandreas.hansson@arm.com code('py::enum_<${wrapper_name}::${enum_name}>(m, "enum_${name}")') 141310458Sandreas.hansson@arm.com 141410458Sandreas.hansson@arm.com code.indent() 141510458Sandreas.hansson@arm.com code.indent() 141610458Sandreas.hansson@arm.com for val in cls.vals: 141710458Sandreas.hansson@arm.com code('.value("${val}", ${wrapper_name}::${val})') 141810458Sandreas.hansson@arm.com code('.value("Num_${name}", ${wrapper_name}::Num_${enum_name})') 141910458Sandreas.hansson@arm.com code('.export_values()') 14204167Sbinkertn@umich.edu code(';') 142110267SGeoffrey.Blake@arm.com code.dedent() 142210267SGeoffrey.Blake@arm.com 14233101Sstever@eecs.umich.edu code('}') 14244167Sbinkertn@umich.edu code.dedent() 14254167Sbinkertn@umich.edu code() 14264167Sbinkertn@umich.edu code('static EmbeddedPyBind embed_enum("enum_${name}", module_init);') 14274167Sbinkertn@umich.edu 14284167Sbinkertn@umich.edu 14294167Sbinkertn@umich.edu# Base class for enum types. 14304167Sbinkertn@umich.educlass Enum(ParamValue): 14314167Sbinkertn@umich.edu __metaclass__ = MetaEnum 14324167Sbinkertn@umich.edu vals = [] 14334167Sbinkertn@umich.edu cmd_line_settable = True 14344167Sbinkertn@umich.edu 14354167Sbinkertn@umich.edu # The name of the wrapping namespace or struct 14363101Sstever@eecs.umich.edu wrapper_name = 'Enums' 143710267SGeoffrey.Blake@arm.com 143810267SGeoffrey.Blake@arm.com # If true, the enum is wrapped in a struct rather than a namespace 143910267SGeoffrey.Blake@arm.com wrapper_is_struct = False 144010267SGeoffrey.Blake@arm.com 14413101Sstever@eecs.umich.edu is_class = False 14423101Sstever@eecs.umich.edu 14433101Sstever@eecs.umich.edu # If not None, use this as the enum name rather than this class name 14443101Sstever@eecs.umich.edu enum_name = None 14453101Sstever@eecs.umich.edu 14463101Sstever@eecs.umich.edu def __init__(self, value): 14473101Sstever@eecs.umich.edu if value not in self.map: 14484762Snate@binkert.org raise TypeError("Enum param got bad value '%s' (not in %s)" \ 14494762Snate@binkert.org % (value, self.vals)) 14504762Snate@binkert.org self.value = value 14514762Snate@binkert.org 14524762Snate@binkert.org def __call__(self, value): 14534762Snate@binkert.org self.__init__(value) 14544762Snate@binkert.org return value 145510380SAndrew.Bardsley@arm.com 145610380SAndrew.Bardsley@arm.com @classmethod 145710380SAndrew.Bardsley@arm.com def cxx_predecls(cls, code): 14583101Sstever@eecs.umich.edu code('#include "enums/$0.hh"', cls.__name__) 14593101Sstever@eecs.umich.edu 14604762Snate@binkert.org @classmethod 14613101Sstever@eecs.umich.edu def cxx_ini_parse(cls, code, src, dest, ret): 14624167Sbinkertn@umich.edu code('if (false) {') 146310267SGeoffrey.Blake@arm.com for elem_name in cls.map.keys(): 146410267SGeoffrey.Blake@arm.com code('} else if (%s == "%s") {' % (src, elem_name)) 14653101Sstever@eecs.umich.edu code.indent() 14664167Sbinkertn@umich.edu code('%s = Enums::%s;' % (dest, elem_name)) 14674167Sbinkertn@umich.edu code('%s true;' % ret) 14684167Sbinkertn@umich.edu code.dedent() 14694167Sbinkertn@umich.edu code('} else {') 14704167Sbinkertn@umich.edu code(' %s false;' % ret) 14714167Sbinkertn@umich.edu code('}') 14724167Sbinkertn@umich.edu 14734167Sbinkertn@umich.edu def getValue(self): 14744167Sbinkertn@umich.edu import m5.internal.params 14754167Sbinkertn@umich.edu e = getattr(m5.internal.params, "enum_%s" % self.__class__.__name__) 14764167Sbinkertn@umich.edu return e(self.map[self.value]) 14774167Sbinkertn@umich.edu 14783101Sstever@eecs.umich.edu def __str__(self): 147910267SGeoffrey.Blake@arm.com return self.value 148010267SGeoffrey.Blake@arm.com 148110267SGeoffrey.Blake@arm.com# This param will generate a scoped c++ enum and its python bindings. 148210267SGeoffrey.Blake@arm.comclass ScopedEnum(Enum): 14833101Sstever@eecs.umich.edu __metaclass__ = MetaEnum 14843101Sstever@eecs.umich.edu vals = [] 14853101Sstever@eecs.umich.edu cmd_line_settable = True 14863101Sstever@eecs.umich.edu 14873101Sstever@eecs.umich.edu # The name of the wrapping namespace or struct 14883101Sstever@eecs.umich.edu wrapper_name = None 14893101Sstever@eecs.umich.edu 14904167Sbinkertn@umich.edu # If true, the enum is wrapped in a struct rather than a namespace 14914762Snate@binkert.org wrapper_is_struct = False 14924762Snate@binkert.org 14934762Snate@binkert.org # If true, the generated enum is a scoped enum 14944762Snate@binkert.org is_class = True 14954762Snate@binkert.org 14964762Snate@binkert.org # If not None, use this as the enum name rather than this class name 14974762Snate@binkert.org enum_name = None 149810380SAndrew.Bardsley@arm.com 149910380SAndrew.Bardsley@arm.com# how big does a rounding error need to be before we warn about it? 150010380SAndrew.Bardsley@arm.comfrequency_tolerance = 0.001 # 0.1% 15013101Sstever@eecs.umich.edu 15024762Snate@binkert.orgclass TickParamValue(NumericParamValue): 15033101Sstever@eecs.umich.edu cxx_type = 'Tick' 150410019Sandreas.hansson@arm.com ex_str = "1MHz" 150510019Sandreas.hansson@arm.com cmd_line_settable = True 150610019Sandreas.hansson@arm.com 15073101Sstever@eecs.umich.edu @classmethod 15084167Sbinkertn@umich.edu def cxx_predecls(cls, code): 15094167Sbinkertn@umich.edu code('#include "base/types.hh"') 15104167Sbinkertn@umich.edu 15114167Sbinkertn@umich.edu def __call__(self, value): 15124167Sbinkertn@umich.edu self.__init__(value) 15134167Sbinkertn@umich.edu return value 15144167Sbinkertn@umich.edu 15154167Sbinkertn@umich.edu def getValue(self): 15164167Sbinkertn@umich.edu return long(self.value) 15174167Sbinkertn@umich.edu 15184167Sbinkertn@umich.edu @classmethod 15194167Sbinkertn@umich.edu def cxx_ini_predecls(cls, code): 15203101Sstever@eecs.umich.edu code('#include <sstream>') 152110267SGeoffrey.Blake@arm.com 152210267SGeoffrey.Blake@arm.com # Ticks are expressed in seconds in JSON files and in plain 152310267SGeoffrey.Blake@arm.com # Ticks in .ini files. Switch based on a config flag 152410267SGeoffrey.Blake@arm.com @classmethod 152510267SGeoffrey.Blake@arm.com def cxx_ini_parse(self, code, src, dest, ret): 152610267SGeoffrey.Blake@arm.com code('${ret} to_number(${src}, ${dest});') 152710267SGeoffrey.Blake@arm.com 15283101Sstever@eecs.umich.educlass Latency(TickParamValue): 15293101Sstever@eecs.umich.edu ex_str = "100ns" 15303101Sstever@eecs.umich.edu 15313101Sstever@eecs.umich.edu def __init__(self, value): 15323101Sstever@eecs.umich.edu if isinstance(value, (Latency, Clock)): 15333101Sstever@eecs.umich.edu self.ticks = value.ticks 15343101Sstever@eecs.umich.edu self.value = value.value 15354762Snate@binkert.org elif isinstance(value, Frequency): 15364762Snate@binkert.org self.ticks = value.ticks 15374762Snate@binkert.org self.value = 1.0 / value.value 153810380SAndrew.Bardsley@arm.com elif value.endswith('t'): 153910380SAndrew.Bardsley@arm.com self.ticks = True 154010380SAndrew.Bardsley@arm.com self.value = int(value[:-1]) 15413101Sstever@eecs.umich.edu else: 15423101Sstever@eecs.umich.edu self.ticks = False 15433101Sstever@eecs.umich.edu self.value = convert.toLatency(value) 154412250Sgabeblack@google.com 154510267SGeoffrey.Blake@arm.com def __call__(self, value): 154610267SGeoffrey.Blake@arm.com self.__init__(value) 15479827Sakash.bagdia@arm.com return value 154812250Sgabeblack@google.com 154912250Sgabeblack@google.com def __getattr__(self, attr): 15509827Sakash.bagdia@arm.com if attr in ('latency', 'period'): 155112250Sgabeblack@google.com return self 155212250Sgabeblack@google.com if attr == 'frequency': 155312250Sgabeblack@google.com return Frequency(self) 155410267SGeoffrey.Blake@arm.com raise AttributeError("Latency object has no attribute '%s'" % attr) 155512250Sgabeblack@google.com 155610427Sandreas.hansson@arm.com def getValue(self): 155710427Sandreas.hansson@arm.com if self.ticks or self.value == 0: 155810427Sandreas.hansson@arm.com value = self.value 155912250Sgabeblack@google.com else: 156012250Sgabeblack@google.com value = ticks.fromSeconds(self.value) 156110427Sandreas.hansson@arm.com return long(value) 156212250Sgabeblack@google.com 156312250Sgabeblack@google.com def config_value(self): 156412250Sgabeblack@google.com return self.getValue() 156510458Sandreas.hansson@arm.com 15663101Sstever@eecs.umich.edu # convert latency to ticks 15673101Sstever@eecs.umich.edu def ini_str(self): 156810267SGeoffrey.Blake@arm.com return '%d' % self.getValue() 156910267SGeoffrey.Blake@arm.com 157010267SGeoffrey.Blake@arm.comclass Frequency(TickParamValue): 15713101Sstever@eecs.umich.edu ex_str = "1GHz" 15724167Sbinkertn@umich.edu 15734167Sbinkertn@umich.edu def __init__(self, value): 15743101Sstever@eecs.umich.edu if isinstance(value, (Latency, Clock)): 15753101Sstever@eecs.umich.edu if value.value == 0: 15763101Sstever@eecs.umich.edu self.value = 0 15773101Sstever@eecs.umich.edu else: 15783101Sstever@eecs.umich.edu self.value = 1.0 / value.value 157910267SGeoffrey.Blake@arm.com self.ticks = value.ticks 158010267SGeoffrey.Blake@arm.com elif isinstance(value, Frequency): 158110267SGeoffrey.Blake@arm.com self.value = value.value 158210267SGeoffrey.Blake@arm.com self.ticks = value.ticks 158310267SGeoffrey.Blake@arm.com else: 15844762Snate@binkert.org self.ticks = False 15854167Sbinkertn@umich.edu self.value = convert.toFrequency(value) 15864167Sbinkertn@umich.edu 15874167Sbinkertn@umich.edu def __call__(self, value): 15884762Snate@binkert.org self.__init__(value) 15894762Snate@binkert.org return value 15904762Snate@binkert.org 15914762Snate@binkert.org def __getattr__(self, attr): 15924762Snate@binkert.org if attr == 'frequency': 15933101Sstever@eecs.umich.edu return self 159410380SAndrew.Bardsley@arm.com if attr in ('latency', 'period'): 159510380SAndrew.Bardsley@arm.com return Latency(self) 159610380SAndrew.Bardsley@arm.com raise AttributeError("Frequency object has no attribute '%s'" % attr) 159710458Sandreas.hansson@arm.com 159810458Sandreas.hansson@arm.com # convert latency to ticks 159910458Sandreas.hansson@arm.com def getValue(self): 160010458Sandreas.hansson@arm.com if self.ticks or self.value == 0: 160110458Sandreas.hansson@arm.com value = self.value 160210458Sandreas.hansson@arm.com else: 160310458Sandreas.hansson@arm.com value = ticks.fromSeconds(1.0 / self.value) 160410458Sandreas.hansson@arm.com return long(value) 16053101Sstever@eecs.umich.edu 16063101Sstever@eecs.umich.edu def config_value(self): 160710267SGeoffrey.Blake@arm.com return self.getValue() 160810267SGeoffrey.Blake@arm.com 160910267SGeoffrey.Blake@arm.com def ini_str(self): 16105469Snate@binkert.org return '%d' % self.getValue() 16117743Sgblack@eecs.umich.edu 16123102Sstever@eecs.umich.edu# A generic Frequency and/or Latency value. Value is stored as a 16133101Sstever@eecs.umich.edu# latency, just like Latency and Frequency. 16143101Sstever@eecs.umich.educlass Clock(TickParamValue): 161510267SGeoffrey.Blake@arm.com def __init__(self, value): 161610267SGeoffrey.Blake@arm.com if isinstance(value, (Latency, Clock)): 161710267SGeoffrey.Blake@arm.com self.ticks = value.ticks 161810267SGeoffrey.Blake@arm.com self.value = value.value 16193101Sstever@eecs.umich.edu elif isinstance(value, Frequency): 16204762Snate@binkert.org self.ticks = value.ticks 16214167Sbinkertn@umich.edu self.value = 1.0 / value.value 16225468Snate@binkert.org elif value.endswith('t'): 16235468Snate@binkert.org self.ticks = True 16245468Snate@binkert.org self.value = int(value[:-1]) 16254167Sbinkertn@umich.edu else: 16264762Snate@binkert.org self.ticks = False 16274762Snate@binkert.org self.value = convert.anyToLatency(value) 16284762Snate@binkert.org 16294762Snate@binkert.org def __call__(self, value): 16304762Snate@binkert.org self.__init__(value) 16313101Sstever@eecs.umich.edu return value 163210380SAndrew.Bardsley@arm.com 163310380SAndrew.Bardsley@arm.com def __str__(self): 163410380SAndrew.Bardsley@arm.com return "%s" % Latency(self) 163510458Sandreas.hansson@arm.com 163610458Sandreas.hansson@arm.com def __getattr__(self, attr): 163710458Sandreas.hansson@arm.com if attr == 'frequency': 163810458Sandreas.hansson@arm.com return Frequency(self) 163910458Sandreas.hansson@arm.com if attr in ('latency', 'period'): 164010458Sandreas.hansson@arm.com return Latency(self) 164110458Sandreas.hansson@arm.com raise AttributeError("Frequency object has no attribute '%s'" % attr) 164210458Sandreas.hansson@arm.com 16433101Sstever@eecs.umich.edu def getValue(self): 16443101Sstever@eecs.umich.edu return self.period.getValue() 16453101Sstever@eecs.umich.edu 16463101Sstever@eecs.umich.edu def config_value(self): 16473102Sstever@eecs.umich.edu return self.period.config_value() 16483102Sstever@eecs.umich.edu 16493102Sstever@eecs.umich.edu def ini_str(self): 16503102Sstever@eecs.umich.edu return self.period.ini_str() 16513102Sstever@eecs.umich.edu 16523102Sstever@eecs.umich.educlass Voltage(Float): 165312197Sgabeblack@google.com ex_str = "1V" 16543102Sstever@eecs.umich.edu 16553102Sstever@eecs.umich.edu def __new__(cls, value): 16563102Sstever@eecs.umich.edu value = convert.toVoltage(value) 16573102Sstever@eecs.umich.edu return super(cls, Voltage).__new__(cls, value) 16583102Sstever@eecs.umich.edu 16593102Sstever@eecs.umich.edu def __init__(self, value): 16603102Sstever@eecs.umich.edu value = convert.toVoltage(value) 16613102Sstever@eecs.umich.edu super(Voltage, self).__init__(value) 16623102Sstever@eecs.umich.edu 16633102Sstever@eecs.umich.educlass Current(Float): 16643102Sstever@eecs.umich.edu ex_str = "1mA" 16653102Sstever@eecs.umich.edu 16663102Sstever@eecs.umich.edu def __new__(cls, value): 16673102Sstever@eecs.umich.edu value = convert.toCurrent(value) 16683102Sstever@eecs.umich.edu return super(cls, Current).__new__(cls, value) 16694762Snate@binkert.org 167012192Sgabeblack@google.com def __init__(self, value): 167112192Sgabeblack@google.com value = convert.toCurrent(value) 167212192Sgabeblack@google.com super(Current, self).__init__(value) 167312195Sgabeblack@google.com 167412195Sgabeblack@google.comclass Energy(Float): 167512195Sgabeblack@google.com ex_str = "1pJ" 167612196Sgabeblack@google.com 167712196Sgabeblack@google.com def __new__(cls, value): 167812196Sgabeblack@google.com value = convert.toEnergy(value) 167912196Sgabeblack@google.com return super(cls, Energy).__new__(cls, value) 168012200Sgabeblack@google.com 168112200Sgabeblack@google.com def __init__(self, value): 168212200Sgabeblack@google.com value = convert.toEnergy(value) 16833102Sstever@eecs.umich.edu super(Energy, self).__init__(value) 168412197Sgabeblack@google.com 16853102Sstever@eecs.umich.educlass NetworkBandwidth(float,ParamValue): 168610380SAndrew.Bardsley@arm.com cxx_type = 'float' 168710380SAndrew.Bardsley@arm.com ex_str = "1Gbps" 168810380SAndrew.Bardsley@arm.com cmd_line_settable = True 16894762Snate@binkert.org 16904762Snate@binkert.org def __new__(cls, value): 16914762Snate@binkert.org # convert to bits per second 16923102Sstever@eecs.umich.edu val = convert.toNetworkBandwidth(value) 16933102Sstever@eecs.umich.edu return super(cls, NetworkBandwidth).__new__(cls, val) 16943102Sstever@eecs.umich.edu 16953102Sstever@eecs.umich.edu def __str__(self): 16963102Sstever@eecs.umich.edu return str(self.val) 16973102Sstever@eecs.umich.edu 16983101Sstever@eecs.umich.edu def __call__(self, value): 16993101Sstever@eecs.umich.edu val = convert.toNetworkBandwidth(value) 17003101Sstever@eecs.umich.edu self.__init__(val) 17013101Sstever@eecs.umich.edu return value 17023101Sstever@eecs.umich.edu 17033101Sstever@eecs.umich.edu def getValue(self): 17043101Sstever@eecs.umich.edu # convert to seconds per byte 17053101Sstever@eecs.umich.edu value = 8.0 / float(self) 17063101Sstever@eecs.umich.edu # convert to ticks per byte 17073101Sstever@eecs.umich.edu value = ticks.fromSeconds(value) 17083101Sstever@eecs.umich.edu return float(value) 17093101Sstever@eecs.umich.edu 17103101Sstever@eecs.umich.edu def ini_str(self): 17113101Sstever@eecs.umich.edu return '%f' % self.getValue() 17123101Sstever@eecs.umich.edu 17133101Sstever@eecs.umich.edu def config_value(self): 17143101Sstever@eecs.umich.edu return '%f' % self.getValue() 17158839Sandreas.hansson@arm.com 17163105Sstever@eecs.umich.edu @classmethod 17173101Sstever@eecs.umich.edu def cxx_ini_predecls(cls, code): 17183101Sstever@eecs.umich.edu code('#include <sstream>') 17198839Sandreas.hansson@arm.com 17203101Sstever@eecs.umich.edu @classmethod 17213101Sstever@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 17223105Sstever@eecs.umich.edu code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 17233101Sstever@eecs.umich.edu 17243103Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue): 17253105Sstever@eecs.umich.edu cxx_type = 'float' 17263103Sstever@eecs.umich.edu ex_str = "1GB/s" 17278840Sandreas.hansson@arm.com cmd_line_settable = True 17288840Sandreas.hansson@arm.com 17298840Sandreas.hansson@arm.com def __new__(cls, value): 17308840Sandreas.hansson@arm.com # convert to bytes per second 17318840Sandreas.hansson@arm.com val = convert.toMemoryBandwidth(value) 17323105Sstever@eecs.umich.edu return super(cls, MemoryBandwidth).__new__(cls, val) 17333105Sstever@eecs.umich.edu 17343105Sstever@eecs.umich.edu def __call__(self, value): 17353105Sstever@eecs.umich.edu val = convert.toMemoryBandwidth(value) 17369017Sandreas.hansson@arm.com self.__init__(val) 17379017Sandreas.hansson@arm.com return value 17389017Sandreas.hansson@arm.com 17399017Sandreas.hansson@arm.com def getValue(self): 17403105Sstever@eecs.umich.edu # convert to seconds per byte 17413105Sstever@eecs.umich.edu value = float(self) 17423105Sstever@eecs.umich.edu if value: 17433105Sstever@eecs.umich.edu value = 1.0 / float(self) 17443105Sstever@eecs.umich.edu # convert to ticks per byte 17453105Sstever@eecs.umich.edu value = ticks.fromSeconds(value) 17463105Sstever@eecs.umich.edu return float(value) 17473105Sstever@eecs.umich.edu 17483105Sstever@eecs.umich.edu def ini_str(self): 17493109Sstever@eecs.umich.edu return '%f' % self.getValue() 17503105Sstever@eecs.umich.edu 17513105Sstever@eecs.umich.edu def config_value(self): 17523105Sstever@eecs.umich.edu return '%f' % self.getValue() 17533105Sstever@eecs.umich.edu 17543105Sstever@eecs.umich.edu @classmethod 17553105Sstever@eecs.umich.edu def cxx_ini_predecls(cls, code): 17569014Sandreas.hansson@arm.com code('#include <sstream>') 17579014Sandreas.hansson@arm.com 17583101Sstever@eecs.umich.edu @classmethod 17593109Sstever@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 17603109Sstever@eecs.umich.edu code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 17613109Sstever@eecs.umich.edu 17623109Sstever@eecs.umich.edu# 17633109Sstever@eecs.umich.edu# "Constants"... handy aliases for various values. 17643109Sstever@eecs.umich.edu# 17653109Sstever@eecs.umich.edu 17663109Sstever@eecs.umich.edu# Special class for NULL pointers. Note the special check in 17673109Sstever@eecs.umich.edu# make_param_value() above that lets these be assigned where a 17683101Sstever@eecs.umich.edu# SimObject is required. 176910355SGeoffrey.Blake@arm.com# only one copy of a particular node 177010355SGeoffrey.Blake@arm.comclass NullSimObject(object): 177110355SGeoffrey.Blake@arm.com __metaclass__ = Singleton 177210355SGeoffrey.Blake@arm.com _name = 'Null' 177310355SGeoffrey.Blake@arm.com 177410355SGeoffrey.Blake@arm.com def __call__(cls): 177510355SGeoffrey.Blake@arm.com return cls 177610355SGeoffrey.Blake@arm.com 177710355SGeoffrey.Blake@arm.com def _instantiate(self, parent = None, path = ''): 177810355SGeoffrey.Blake@arm.com pass 177910355SGeoffrey.Blake@arm.com 178010355SGeoffrey.Blake@arm.com def ini_str(self): 178110355SGeoffrey.Blake@arm.com return 'Null' 178210355SGeoffrey.Blake@arm.com 178310355SGeoffrey.Blake@arm.com def unproxy(self, base): 178410355SGeoffrey.Blake@arm.com return self 178510355SGeoffrey.Blake@arm.com 178610355SGeoffrey.Blake@arm.com def set_path(self, parent, name): 178710355SGeoffrey.Blake@arm.com pass 178810355SGeoffrey.Blake@arm.com 178910355SGeoffrey.Blake@arm.com def set_parent(self, parent, name): 179010355SGeoffrey.Blake@arm.com pass 179110355SGeoffrey.Blake@arm.com 179210355SGeoffrey.Blake@arm.com def clear_parent(self, old_parent): 179310355SGeoffrey.Blake@arm.com pass 179410355SGeoffrey.Blake@arm.com 179510355SGeoffrey.Blake@arm.com def descendants(self): 179610355SGeoffrey.Blake@arm.com return 179710355SGeoffrey.Blake@arm.com yield None 179810355SGeoffrey.Blake@arm.com 17993105Sstever@eecs.umich.edu def get_config_as_dict(self): 18003105Sstever@eecs.umich.edu return {} 18013105Sstever@eecs.umich.edu 18023101Sstever@eecs.umich.edu def __str__(self): 18033105Sstever@eecs.umich.edu return self._name 18043105Sstever@eecs.umich.edu 18053101Sstever@eecs.umich.edu def config_value(self): 18063105Sstever@eecs.umich.edu return None 18073179Sstever@eecs.umich.edu 18083105Sstever@eecs.umich.edu def getValue(self): 18093105Sstever@eecs.umich.edu return None 18103101Sstever@eecs.umich.edu 18113101Sstever@eecs.umich.edu# The only instance you'll ever need... 18123105Sstever@eecs.umich.eduNULL = NullSimObject() 18133105Sstever@eecs.umich.edu 18143105Sstever@eecs.umich.edudef isNullPointer(value): 18153105Sstever@eecs.umich.edu return isinstance(value, NullSimObject) 18163105Sstever@eecs.umich.edu 18173105Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound. 18183105Sstever@eecs.umich.eduMaxAddr = Addr.max 18193105Sstever@eecs.umich.eduMaxTick = Tick.max 18203105Sstever@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr) 18213105Sstever@eecs.umich.edu 18223105Sstever@eecs.umich.edu 18233101Sstever@eecs.umich.edu##################################################################### 18243101Sstever@eecs.umich.edu# 182511802Sandreas.sandberg@arm.com# Port objects 18264762Snate@binkert.org# 18278839Sandreas.hansson@arm.com# Ports are used to interconnect objects in the memory system. 18288839Sandreas.hansson@arm.com# 18298839Sandreas.hansson@arm.com##################################################################### 18308839Sandreas.hansson@arm.com 18313101Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a 18323101Sstever@eecs.umich.edu# particular SimObject. 18333101Sstever@eecs.umich.educlass PortRef(object): 18345578SSteve.Reinhardt@amd.com def __init__(self, simobj, name, role): 18355578SSteve.Reinhardt@amd.com assert(isSimObject(simobj) or isSimObjectClass(simobj)) 18368839Sandreas.hansson@arm.com self.simobj = simobj 18378839Sandreas.hansson@arm.com self.name = name 18388839Sandreas.hansson@arm.com self.role = role 18398839Sandreas.hansson@arm.com self.peer = None # not associated with another port yet 18408839Sandreas.hansson@arm.com self.ccConnected = False # C++ port connection done? 18418839Sandreas.hansson@arm.com self.index = -1 # always -1 for non-vector ports 18428839Sandreas.hansson@arm.com 18437526Ssteve.reinhardt@amd.com def __str__(self): 18448839Sandreas.hansson@arm.com return '%s.%s' % (self.simobj, self.name) 18457526Ssteve.reinhardt@amd.com 18467526Ssteve.reinhardt@amd.com def __len__(self): 18477526Ssteve.reinhardt@amd.com # Return the number of connected ports, i.e. 0 is we have no 18487526Ssteve.reinhardt@amd.com # peer and 1 if we do. 18497526Ssteve.reinhardt@amd.com return int(self.peer != None) 18507526Ssteve.reinhardt@amd.com 18517526Ssteve.reinhardt@amd.com # for config.ini, print peer's name (not ours) 18523101Sstever@eecs.umich.edu def ini_str(self): 18533101Sstever@eecs.umich.edu return str(self.peer) 18543101Sstever@eecs.umich.edu 18553105Sstever@eecs.umich.edu # for config.json 18563105Sstever@eecs.umich.edu def get_config_as_dict(self): 18573105Sstever@eecs.umich.edu return {'role' : self.role, 'peer' : str(self.peer)} 18588839Sandreas.hansson@arm.com 18598839Sandreas.hansson@arm.com def __getattr__(self, attr): 18603105Sstever@eecs.umich.edu if attr == 'peerObj': 18613105Sstever@eecs.umich.edu # shorthand for proxies 18623105Sstever@eecs.umich.edu return self.peer.simobj 18633105Sstever@eecs.umich.edu raise AttributeError("'%s' object has no attribute '%s'" % \ 18643105Sstever@eecs.umich.edu (self.__class__.__name__, attr)) 18653105Sstever@eecs.umich.edu 18663105Sstever@eecs.umich.edu # Full connection is symmetric (both ways). Called via 18673105Sstever@eecs.umich.edu # SimObject.__setattr__ as a result of a port assignment, e.g., 18688839Sandreas.hansson@arm.com # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 18693105Sstever@eecs.umich.edu # e.g., "obj1.portA[3] = obj2.portB". 18703105Sstever@eecs.umich.edu def connect(self, other): 18713105Sstever@eecs.umich.edu if isinstance(other, VectorPortRef): 18728839Sandreas.hansson@arm.com # reference to plain VectorPort is implicit append 18733105Sstever@eecs.umich.edu other = other._get_next() 18743105Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 18753109Sstever@eecs.umich.edu fatal("Port %s is already connected to %s, cannot connect %s\n", 18763109Sstever@eecs.umich.edu self, self.peer, other); 18773109Sstever@eecs.umich.edu self.peer = other 18788840Sandreas.hansson@arm.com if proxy.isproxy(other): 18798840Sandreas.hansson@arm.com other.set_param_desc(PortParamDesc()) 18808840Sandreas.hansson@arm.com elif isinstance(other, PortRef): 18818840Sandreas.hansson@arm.com if other.peer is not self: 18828840Sandreas.hansson@arm.com other.connect(self) 18833105Sstever@eecs.umich.edu else: 18843105Sstever@eecs.umich.edu raise TypeError("assigning non-port reference '%s' to port '%s'" \ 18853105Sstever@eecs.umich.edu % (other, self)) 18863105Sstever@eecs.umich.edu 18879017Sandreas.hansson@arm.com # Allow a master/slave port pair to be spliced between 18889017Sandreas.hansson@arm.com # a port and its connected peer. Useful operation for connecting 18899017Sandreas.hansson@arm.com # instrumentation structures into a system when it is necessary 18909017Sandreas.hansson@arm.com # to connect the instrumentation after the full system has been 18919017Sandreas.hansson@arm.com # constructed. 18923105Sstever@eecs.umich.edu def splice(self, new_master_peer, new_slave_peer): 18933105Sstever@eecs.umich.edu if not self.peer or proxy.isproxy(self.peer): 18943105Sstever@eecs.umich.edu fatal("Port %s not connected, cannot splice in new peers\n", self) 18953105Sstever@eecs.umich.edu 18963105Sstever@eecs.umich.edu if not isinstance(new_master_peer, PortRef) or \ 18978839Sandreas.hansson@arm.com not isinstance(new_slave_peer, PortRef): 18983105Sstever@eecs.umich.edu raise TypeError( 18993105Sstever@eecs.umich.edu "Splicing non-port references '%s','%s' to port '%s'" % \ 19003105Sstever@eecs.umich.edu (new_master_peer, new_slave_peer, self)) 19013105Sstever@eecs.umich.edu 19023105Sstever@eecs.umich.edu old_peer = self.peer 19033105Sstever@eecs.umich.edu if self.role == 'SLAVE': 19043105Sstever@eecs.umich.edu self.peer = new_master_peer 19053105Sstever@eecs.umich.edu old_peer.peer = new_slave_peer 19063105Sstever@eecs.umich.edu new_master_peer.connect(self) 19073105Sstever@eecs.umich.edu new_slave_peer.connect(old_peer) 19083105Sstever@eecs.umich.edu elif self.role == 'MASTER': 19093105Sstever@eecs.umich.edu self.peer = new_slave_peer 19103105Sstever@eecs.umich.edu old_peer.peer = new_master_peer 19113109Sstever@eecs.umich.edu new_slave_peer.connect(self) 19123109Sstever@eecs.umich.edu new_master_peer.connect(old_peer) 19133109Sstever@eecs.umich.edu else: 19143109Sstever@eecs.umich.edu panic("Port %s has unknown role, "+\ 19153109Sstever@eecs.umich.edu "cannot splice in new peers\n", self) 19163109Sstever@eecs.umich.edu 19173109Sstever@eecs.umich.edu def clone(self, simobj, memo): 19183109Sstever@eecs.umich.edu if self in memo: 19193109Sstever@eecs.umich.edu return memo[self] 19203109Sstever@eecs.umich.edu newRef = copy.copy(self) 19213109Sstever@eecs.umich.edu memo[self] = newRef 19223109Sstever@eecs.umich.edu newRef.simobj = simobj 19233109Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 19243109Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 19253109Sstever@eecs.umich.edu peerObj = self.peer.simobj(_memo=memo) 19263109Sstever@eecs.umich.edu newRef.peer = self.peer.clone(peerObj, memo) 19273109Sstever@eecs.umich.edu assert(not isinstance(newRef.peer, VectorPortRef)) 19283109Sstever@eecs.umich.edu return newRef 19293109Sstever@eecs.umich.edu 19303105Sstever@eecs.umich.edu def unproxy(self, simobj): 19313105Sstever@eecs.umich.edu assert(simobj is self.simobj) 19323105Sstever@eecs.umich.edu if proxy.isproxy(self.peer): 19333105Sstever@eecs.umich.edu try: 19343105Sstever@eecs.umich.edu realPeer = self.peer.unproxy(self.simobj) 19353105Sstever@eecs.umich.edu except: 19363105Sstever@eecs.umich.edu print("Error in unproxying port '%s' of %s" % 19373101Sstever@eecs.umich.edu (self.name, self.simobj.path())) 19383101Sstever@eecs.umich.edu raise 19393101Sstever@eecs.umich.edu self.connect(realPeer) 19403101Sstever@eecs.umich.edu 19413101Sstever@eecs.umich.edu # Call C++ to create corresponding port connection between C++ objects 19423101Sstever@eecs.umich.edu def ccConnect(self): 19433105Sstever@eecs.umich.edu from _m5.pyobject import connectPorts 19448839Sandreas.hansson@arm.com 19453101Sstever@eecs.umich.edu if self.ccConnected: # already done this 19463101Sstever@eecs.umich.edu return 19473101Sstever@eecs.umich.edu 19483105Sstever@eecs.umich.edu peer = self.peer 19493105Sstever@eecs.umich.edu if not self.peer: # nothing to connect to 19503101Sstever@eecs.umich.edu return 19518840Sandreas.hansson@arm.com 19528840Sandreas.hansson@arm.com # check that we connect a master to a slave 19538840Sandreas.hansson@arm.com if self.role == peer.role: 19548840Sandreas.hansson@arm.com raise TypeError( 19558840Sandreas.hansson@arm.com "cannot connect '%s' and '%s' due to identical role '%s'" % \ 195611988Sandreas.sandberg@arm.com (peer, self, self.role)) 195711988Sandreas.sandberg@arm.com 195811988Sandreas.sandberg@arm.com if self.role == 'SLAVE': 19598840Sandreas.hansson@arm.com # do nothing and let the master take care of it 19608840Sandreas.hansson@arm.com return 19618840Sandreas.hansson@arm.com 19628840Sandreas.hansson@arm.com try: 19638840Sandreas.hansson@arm.com # self is always the master and peer the slave 19648840Sandreas.hansson@arm.com connectPorts(self.simobj.getCCObject(), self.name, self.index, 19658839Sandreas.hansson@arm.com peer.simobj.getCCObject(), peer.name, peer.index) 19668839Sandreas.hansson@arm.com except: 19678839Sandreas.hansson@arm.com print("Error connecting port %s.%s to %s.%s" % 19688839Sandreas.hansson@arm.com (self.simobj.path(), self.name, 19698839Sandreas.hansson@arm.com peer.simobj.path(), peer.name)) 19708839Sandreas.hansson@arm.com raise 19718839Sandreas.hansson@arm.com self.ccConnected = True 19728839Sandreas.hansson@arm.com peer.ccConnected = True 19738839Sandreas.hansson@arm.com 19748839Sandreas.hansson@arm.com# A reference to an individual element of a VectorPort... much like a 19758839Sandreas.hansson@arm.com# PortRef, but has an index. 19768839Sandreas.hansson@arm.comclass VectorPortElementRef(PortRef): 19778839Sandreas.hansson@arm.com def __init__(self, simobj, name, role, index): 19788839Sandreas.hansson@arm.com PortRef.__init__(self, simobj, name, role) 19798839Sandreas.hansson@arm.com self.index = index 19808839Sandreas.hansson@arm.com 19818839Sandreas.hansson@arm.com def __str__(self): 19828839Sandreas.hansson@arm.com return '%s.%s[%d]' % (self.simobj, self.name, self.index) 19833101Sstever@eecs.umich.edu 198410405Sandreas.hansson@arm.com# A reference to a complete vector-valued port (not just a single element). 19853101Sstever@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances. 19863105Sstever@eecs.umich.educlass VectorPortRef(object): 19873101Sstever@eecs.umich.edu def __init__(self, simobj, name, role): 19883101Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 19893105Sstever@eecs.umich.edu self.simobj = simobj 19908839Sandreas.hansson@arm.com self.name = name 19918839Sandreas.hansson@arm.com self.role = role 19928839Sandreas.hansson@arm.com self.elements = [] 19938839Sandreas.hansson@arm.com 19948839Sandreas.hansson@arm.com def __str__(self): 19958839Sandreas.hansson@arm.com return '%s.%s[:]' % (self.simobj, self.name) 19968839Sandreas.hansson@arm.com 19978839Sandreas.hansson@arm.com def __len__(self): 19988839Sandreas.hansson@arm.com # Return the number of connected peers, corresponding the the 19998839Sandreas.hansson@arm.com # length of the elements. 20008839Sandreas.hansson@arm.com return len(self.elements) 20018839Sandreas.hansson@arm.com 20028839Sandreas.hansson@arm.com # for config.ini, print peer's name (not ours) 20038839Sandreas.hansson@arm.com def ini_str(self): 20048839Sandreas.hansson@arm.com return ' '.join([el.ini_str() for el in self.elements]) 20058839Sandreas.hansson@arm.com 20068839Sandreas.hansson@arm.com # for config.json 20078839Sandreas.hansson@arm.com def get_config_as_dict(self): 20088839Sandreas.hansson@arm.com return {'role' : self.role, 20098839Sandreas.hansson@arm.com 'peer' : [el.ini_str() for el in self.elements]} 20108839Sandreas.hansson@arm.com 20113105Sstever@eecs.umich.edu def __getitem__(self, key): 20123109Sstever@eecs.umich.edu if not isinstance(key, int): 20133109Sstever@eecs.umich.edu raise TypeError("VectorPort index must be integer") 20143109Sstever@eecs.umich.edu if key >= len(self.elements): 20153109Sstever@eecs.umich.edu # need to extend list 20163109Sstever@eecs.umich.edu ext = [VectorPortElementRef(self.simobj, self.name, self.role, i) 20173109Sstever@eecs.umich.edu for i in range(len(self.elements), key+1)] 20183109Sstever@eecs.umich.edu self.elements.extend(ext) 20193109Sstever@eecs.umich.edu return self.elements[key] 20203105Sstever@eecs.umich.edu 20216654Snate@binkert.org def _get_next(self): 20226654Snate@binkert.org return self[len(self.elements)] 20236654Snate@binkert.org 20246654Snate@binkert.org def __setitem__(self, key, value): 20256654Snate@binkert.org if not isinstance(key, int): 20266654Snate@binkert.org raise TypeError("VectorPort index must be integer") 20276654Snate@binkert.org self[key].connect(value) 20286654Snate@binkert.org 20296654Snate@binkert.org def connect(self, other): 20303101Sstever@eecs.umich.edu if isinstance(other, (list, tuple)): 20313101Sstever@eecs.umich.edu # Assign list of port refs to vector port. 20323101Sstever@eecs.umich.edu # For now, append them... not sure if that's the right semantics 20333101Sstever@eecs.umich.edu # or if it should replace the current vector. 20343101Sstever@eecs.umich.edu for ref in other: 20353101Sstever@eecs.umich.edu self._get_next().connect(ref) 20367777Sgblack@eecs.umich.edu else: 20373101Sstever@eecs.umich.edu # scalar assignment to plain VectorPort is implicit append 20389827Sakash.bagdia@arm.com self._get_next().connect(other) 20393101Sstever@eecs.umich.edu 20409232Sandreas.hansson@arm.com def clone(self, simobj, memo): 20413101Sstever@eecs.umich.edu if self in memo: 20423885Sbinkertn@umich.edu return memo[self] 20433102Sstever@eecs.umich.edu newRef = copy.copy(self) 20448839Sandreas.hansson@arm.com memo[self] = newRef 20458839Sandreas.hansson@arm.com newRef.simobj = simobj 20466654Snate@binkert.org assert(isSimObject(newRef.simobj)) 20476654Snate@binkert.org newRef.elements = [el.clone(simobj, memo) for el in self.elements] 2048 return newRef 2049 2050 def unproxy(self, simobj): 2051 [el.unproxy(simobj) for el in self.elements] 2052 2053 def ccConnect(self): 2054 [el.ccConnect() for el in self.elements] 2055 2056# Port description object. Like a ParamDesc object, this represents a 2057# logical port in the SimObject class, not a particular port on a 2058# SimObject instance. The latter are represented by PortRef objects. 2059class Port(object): 2060 # Generate a PortRef for this port on the given SimObject with the 2061 # given name 2062 def makeRef(self, simobj): 2063 return PortRef(simobj, self.name, self.role) 2064 2065 # Connect an instance of this port (on the given SimObject with 2066 # the given name) with the port described by the supplied PortRef 2067 def connect(self, simobj, ref): 2068 self.makeRef(simobj).connect(ref) 2069 2070 # No need for any pre-declarations at the moment as we merely rely 2071 # on an unsigned int. 2072 def cxx_predecls(self, code): 2073 pass 2074 2075 def pybind_predecls(self, code): 2076 cls.cxx_predecls(self, code) 2077 2078 # Declare an unsigned int with the same name as the port, that 2079 # will eventually hold the number of connected ports (and thus the 2080 # number of elements for a VectorPort). 2081 def cxx_decl(self, code): 2082 code('unsigned int port_${{self.name}}_connection_count;') 2083 2084class MasterPort(Port): 2085 # MasterPort("description") 2086 def __init__(self, *args): 2087 if len(args) == 1: 2088 self.desc = args[0] 2089 self.role = 'MASTER' 2090 else: 2091 raise TypeError('wrong number of arguments') 2092 2093class SlavePort(Port): 2094 # SlavePort("description") 2095 def __init__(self, *args): 2096 if len(args) == 1: 2097 self.desc = args[0] 2098 self.role = 'SLAVE' 2099 else: 2100 raise TypeError('wrong number of arguments') 2101 2102# VectorPort description object. Like Port, but represents a vector 2103# of connections (e.g., as on a XBar). 2104class VectorPort(Port): 2105 def __init__(self, *args): 2106 self.isVec = True 2107 2108 def makeRef(self, simobj): 2109 return VectorPortRef(simobj, self.name, self.role) 2110 2111class VectorMasterPort(VectorPort): 2112 # VectorMasterPort("description") 2113 def __init__(self, *args): 2114 if len(args) == 1: 2115 self.desc = args[0] 2116 self.role = 'MASTER' 2117 VectorPort.__init__(self, *args) 2118 else: 2119 raise TypeError('wrong number of arguments') 2120 2121class VectorSlavePort(VectorPort): 2122 # VectorSlavePort("description") 2123 def __init__(self, *args): 2124 if len(args) == 1: 2125 self.desc = args[0] 2126 self.role = 'SLAVE' 2127 VectorPort.__init__(self, *args) 2128 else: 2129 raise TypeError('wrong number of arguments') 2130 2131# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 2132# proxy objects (via set_param_desc()) so that proxy error messages 2133# make sense. 2134class PortParamDesc(object): 2135 __metaclass__ = Singleton 2136 2137 ptype_str = 'Port' 2138 ptype = Port 2139 2140baseEnums = allEnums.copy() 2141baseParams = allParams.copy() 2142 2143def clear(): 2144 global allEnums, allParams 2145 2146 allEnums = baseEnums.copy() 2147 allParams = baseParams.copy() 2148 2149__all__ = ['Param', 'VectorParam', 2150 'Enum', 'ScopedEnum', 'Bool', 'String', 'Float', 2151 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 2152 'Int32', 'UInt32', 'Int64', 'UInt64', 2153 'Counter', 'Addr', 'Tick', 'Percent', 2154 'TcpPort', 'UdpPort', 'EthernetAddr', 2155 'IpAddress', 'IpNetmask', 'IpWithPort', 2156 'MemorySize', 'MemorySize32', 2157 'Latency', 'Frequency', 'Clock', 'Voltage', 'Current', 'Energy', 2158 'NetworkBandwidth', 'MemoryBandwidth', 2159 'AddrRange', 2160 'MaxAddr', 'MaxTick', 'AllMemory', 2161 'Time', 2162 'NextEthernetAddr', 'NULL', 2163 'MasterPort', 'SlavePort', 2164 'VectorMasterPort', 'VectorSlavePort'] 2165