params.py revision 13714
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 return SimObject.isSimObject(*args, **kwargs) 774762Snate@binkert.org 784762Snate@binkert.orgdef isSimObjectSequence(*args, **kwargs): 794762Snate@binkert.org return SimObject.isSimObjectSequence(*args, **kwargs) 804762Snate@binkert.org 814762Snate@binkert.orgdef isSimObjectClass(*args, **kwargs): 825033Smilesck@eecs.umich.edu return SimObject.isSimObjectClass(*args, **kwargs) 835033Smilesck@eecs.umich.edu 845033Smilesck@eecs.umich.eduallParams = {} 855033Smilesck@eecs.umich.edu 865033Smilesck@eecs.umich.educlass MetaParamValue(type): 875033Smilesck@eecs.umich.edu def __new__(mcls, name, bases, dct): 885033Smilesck@eecs.umich.edu cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) 895033Smilesck@eecs.umich.edu assert name not in allParams 905033Smilesck@eecs.umich.edu allParams[name] = cls 915033Smilesck@eecs.umich.edu return cls 923101Sstever@eecs.umich.edu 933101Sstever@eecs.umich.edu 943101Sstever@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject 955033Smilesck@eecs.umich.edu# parameters. 9610267SGeoffrey.Blake@arm.comclass ParamValue(object): 978596Ssteve.reinhardt@amd.com __metaclass__ = MetaParamValue 988596Ssteve.reinhardt@amd.com cmd_line_settable = False 998596Ssteve.reinhardt@amd.com 1008596Ssteve.reinhardt@amd.com # Generate the code needed as a prerequisite for declaring a C++ 1017673Snate@binkert.org # object of this type. Typically generates one or more #include 1027673Snate@binkert.org # statements. Used when declaring parameters of this type. 1037673Snate@binkert.org @classmethod 1047673Snate@binkert.org def cxx_predecls(cls, code): 10511988Sandreas.sandberg@arm.com pass 10611988Sandreas.sandberg@arm.com 10711988Sandreas.sandberg@arm.com @classmethod 10811988Sandreas.sandberg@arm.com def pybind_predecls(cls, code): 1093101Sstever@eecs.umich.edu cls.cxx_predecls(code) 1103101Sstever@eecs.umich.edu 1113101Sstever@eecs.umich.edu # default for printing to .ini file is regular string conversion. 1123101Sstever@eecs.umich.edu # will be overridden in some cases 1133101Sstever@eecs.umich.edu def ini_str(self): 11410380SAndrew.Bardsley@arm.com return str(self) 11510380SAndrew.Bardsley@arm.com 11610380SAndrew.Bardsley@arm.com # default for printing to .json file is regular string conversion. 11710380SAndrew.Bardsley@arm.com # will be overridden in some cases, mostly to use native Python 11810380SAndrew.Bardsley@arm.com # types where there are similar JSON types 11910380SAndrew.Bardsley@arm.com def config_value(self): 12010458Sandreas.hansson@arm.com return str(self) 12110458Sandreas.hansson@arm.com 12210458Sandreas.hansson@arm.com # Prerequisites for .ini parsing with cxx_ini_parse 12310458Sandreas.hansson@arm.com @classmethod 12410458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 12510458Sandreas.hansson@arm.com pass 12610458Sandreas.hansson@arm.com 12710458Sandreas.hansson@arm.com # parse a .ini file entry for this param from string expression 12810458Sandreas.hansson@arm.com # src into lvalue dest (of the param's C++ type) 12910458Sandreas.hansson@arm.com @classmethod 13010458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 13110458Sandreas.hansson@arm.com code('// Unhandled param type: %s' % cls.__name__) 1323101Sstever@eecs.umich.edu code('%s false;' % ret) 1333101Sstever@eecs.umich.edu 1343101Sstever@eecs.umich.edu # allows us to blithely call unproxy() on things without checking 1353101Sstever@eecs.umich.edu # if they're really proxies or not 1363101Sstever@eecs.umich.edu def unproxy(self, base): 13710267SGeoffrey.Blake@arm.com return self 13810267SGeoffrey.Blake@arm.com 13910267SGeoffrey.Blake@arm.com # Produce a human readable version of the stored value 14010267SGeoffrey.Blake@arm.com def pretty_print(self, value): 1413101Sstever@eecs.umich.edu return str(value) 1423101Sstever@eecs.umich.edu 1433101Sstever@eecs.umich.edu# Regular parameter description. 1443101Sstever@eecs.umich.educlass ParamDesc(object): 1453101Sstever@eecs.umich.edu def __init__(self, ptype_str, ptype, *args, **kwargs): 1463101Sstever@eecs.umich.edu self.ptype_str = ptype_str 1473101Sstever@eecs.umich.edu # remember ptype only if it is provided 1483101Sstever@eecs.umich.edu if ptype != None: 1493101Sstever@eecs.umich.edu self.ptype = ptype 1503101Sstever@eecs.umich.edu 1513101Sstever@eecs.umich.edu if args: 1523101Sstever@eecs.umich.edu if len(args) == 1: 1533101Sstever@eecs.umich.edu self.desc = args[0] 1543101Sstever@eecs.umich.edu elif len(args) == 2: 1553101Sstever@eecs.umich.edu self.default = args[0] 1563101Sstever@eecs.umich.edu self.desc = args[1] 1573101Sstever@eecs.umich.edu else: 1583101Sstever@eecs.umich.edu raise TypeError('too many arguments') 1593101Sstever@eecs.umich.edu 1603101Sstever@eecs.umich.edu if 'desc' in kwargs: 1613101Sstever@eecs.umich.edu assert(not hasattr(self, 'desc')) 1623101Sstever@eecs.umich.edu self.desc = kwargs['desc'] 1633101Sstever@eecs.umich.edu del kwargs['desc'] 1643101Sstever@eecs.umich.edu 1653101Sstever@eecs.umich.edu if 'default' in kwargs: 1663101Sstever@eecs.umich.edu assert(not hasattr(self, 'default')) 1673101Sstever@eecs.umich.edu self.default = kwargs['default'] 1683101Sstever@eecs.umich.edu del kwargs['default'] 1693101Sstever@eecs.umich.edu 1703101Sstever@eecs.umich.edu if kwargs: 1713101Sstever@eecs.umich.edu raise TypeError('extra unknown kwargs %s' % kwargs) 1723101Sstever@eecs.umich.edu 1733101Sstever@eecs.umich.edu if not hasattr(self, 'desc'): 1743101Sstever@eecs.umich.edu raise TypeError('desc attribute missing') 1753101Sstever@eecs.umich.edu 1765033Smilesck@eecs.umich.edu def __getattr__(self, attr): 1776656Snate@binkert.org if attr == 'ptype': 1785033Smilesck@eecs.umich.edu ptype = SimObject.allClasses[self.ptype_str] 1795033Smilesck@eecs.umich.edu assert isSimObjectClass(ptype) 1805033Smilesck@eecs.umich.edu self.ptype = ptype 1813101Sstever@eecs.umich.edu return ptype 1823101Sstever@eecs.umich.edu 1833101Sstever@eecs.umich.edu raise AttributeError("'%s' object has no attribute '%s'" % \ 18410267SGeoffrey.Blake@arm.com (type(self).__name__, attr)) 18510267SGeoffrey.Blake@arm.com 18610267SGeoffrey.Blake@arm.com def example_str(self): 18710267SGeoffrey.Blake@arm.com if hasattr(self.ptype, "ex_str"): 18810267SGeoffrey.Blake@arm.com return self.ptype.ex_str 18910267SGeoffrey.Blake@arm.com else: 19010267SGeoffrey.Blake@arm.com return self.ptype_str 19110267SGeoffrey.Blake@arm.com 19210267SGeoffrey.Blake@arm.com # Is the param available to be exposed on the command line 19310267SGeoffrey.Blake@arm.com def isCmdLineSettable(self): 19410267SGeoffrey.Blake@arm.com if hasattr(self.ptype, "cmd_line_settable"): 19510267SGeoffrey.Blake@arm.com return self.ptype.cmd_line_settable 19610267SGeoffrey.Blake@arm.com else: 1973101Sstever@eecs.umich.edu return False 1983101Sstever@eecs.umich.edu 1993101Sstever@eecs.umich.edu def convert(self, value): 2003101Sstever@eecs.umich.edu if isinstance(value, proxy.BaseProxy): 2013101Sstever@eecs.umich.edu value.set_param_desc(self) 2023101Sstever@eecs.umich.edu return value 2033101Sstever@eecs.umich.edu if 'ptype' not in self.__dict__ and isNullPointer(value): 2043101Sstever@eecs.umich.edu # deferred evaluation of SimObject; continue to defer if 2053101Sstever@eecs.umich.edu # we're just assigning a null pointer 2063101Sstever@eecs.umich.edu return value 2073102Sstever@eecs.umich.edu if isinstance(value, self.ptype): 2083101Sstever@eecs.umich.edu return value 2093101Sstever@eecs.umich.edu if isNullPointer(value) and isSimObjectClass(self.ptype): 2103101Sstever@eecs.umich.edu return value 21110267SGeoffrey.Blake@arm.com return self.ptype(value) 21210267SGeoffrey.Blake@arm.com 21310267SGeoffrey.Blake@arm.com def pretty_print(self, value): 21410267SGeoffrey.Blake@arm.com if isinstance(value, proxy.BaseProxy): 21510267SGeoffrey.Blake@arm.com return str(value) 21610267SGeoffrey.Blake@arm.com if isNullPointer(value): 21710267SGeoffrey.Blake@arm.com return NULL 2187673Snate@binkert.org return self.ptype(value).pretty_print(value) 2198607Sgblack@eecs.umich.edu 2207673Snate@binkert.org def cxx_predecls(self, code): 2213101Sstever@eecs.umich.edu code('#include <cstddef>') 22211988Sandreas.sandberg@arm.com self.ptype.cxx_predecls(code) 22311988Sandreas.sandberg@arm.com 22411988Sandreas.sandberg@arm.com def pybind_predecls(self, code): 2257673Snate@binkert.org self.ptype.pybind_predecls(code) 2267673Snate@binkert.org 2273101Sstever@eecs.umich.edu def cxx_decl(self, code): 2283101Sstever@eecs.umich.edu code('${{self.ptype.cxx_type}} ${{self.name}};') 2293101Sstever@eecs.umich.edu 2303101Sstever@eecs.umich.edu# Vector-valued parameter description. Just like ParamDesc, except 2313101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a 2323101Sstever@eecs.umich.edu# single value. 2335033Smilesck@eecs.umich.edu 2345475Snate@binkert.orgclass VectorParamValue(list): 2355475Snate@binkert.org __metaclass__ = MetaParamValue 2365475Snate@binkert.org def __setattr__(self, attr, value): 2375475Snate@binkert.org raise AttributeError("Not allowed to set %s on '%s'" % \ 23810380SAndrew.Bardsley@arm.com (attr, type(self).__name__)) 23910380SAndrew.Bardsley@arm.com 24010380SAndrew.Bardsley@arm.com def config_value(self): 2413101Sstever@eecs.umich.edu return [v.config_value() for v in self] 2423101Sstever@eecs.umich.edu 2433101Sstever@eecs.umich.edu def ini_str(self): 2444762Snate@binkert.org return ' '.join([v.ini_str() for v in self]) 2454762Snate@binkert.org 2464762Snate@binkert.org def getValue(self): 2473101Sstever@eecs.umich.edu return [ v.getValue() for v in self ] 24812050Snikos.nikoleris@arm.com 24912050Snikos.nikoleris@arm.com def unproxy(self, base): 25012050Snikos.nikoleris@arm.com if len(self) == 1 and isinstance(self[0], proxy.BaseProxy): 2518459SAli.Saidi@ARM.com # The value is a proxy (e.g. Parent.any, Parent.all or 2528459SAli.Saidi@ARM.com # Parent.x) therefore try resolve it 25312050Snikos.nikoleris@arm.com return self[0].unproxy(base) 2543101Sstever@eecs.umich.edu else: 2557528Ssteve.reinhardt@amd.com return [v.unproxy(base) for v in self] 2567528Ssteve.reinhardt@amd.com 2577528Ssteve.reinhardt@amd.comclass SimObjectVector(VectorParamValue): 2587528Ssteve.reinhardt@amd.com # support clone operation 2597528Ssteve.reinhardt@amd.com def __call__(self, **kwargs): 2607528Ssteve.reinhardt@amd.com return SimObjectVector([v(**kwargs) for v in self]) 2613101Sstever@eecs.umich.edu 2627528Ssteve.reinhardt@amd.com def clear_parent(self, old_parent): 2637528Ssteve.reinhardt@amd.com for v in self: 2647528Ssteve.reinhardt@amd.com v.clear_parent(old_parent) 2657528Ssteve.reinhardt@amd.com 2667528Ssteve.reinhardt@amd.com def set_parent(self, parent, name): 2677528Ssteve.reinhardt@amd.com if len(self) == 1: 2687528Ssteve.reinhardt@amd.com self[0].set_parent(parent, name) 2697528Ssteve.reinhardt@amd.com else: 2707528Ssteve.reinhardt@amd.com width = int(math.ceil(math.log(len(self))/math.log(10))) 2717528Ssteve.reinhardt@amd.com for i,v in enumerate(self): 2728321Ssteve.reinhardt@amd.com v.set_parent(parent, "%s%0*d" % (name, width, i)) 27312194Sgabeblack@google.com 2747528Ssteve.reinhardt@amd.com def has_parent(self): 2757528Ssteve.reinhardt@amd.com return any([e.has_parent() for e in self if not isNullPointer(e)]) 2767528Ssteve.reinhardt@amd.com 2777528Ssteve.reinhardt@amd.com # return 'cpu0 cpu1' etc. for print_ini() 2787528Ssteve.reinhardt@amd.com def get_name(self): 2797528Ssteve.reinhardt@amd.com return ' '.join([v._name for v in self]) 2807528Ssteve.reinhardt@amd.com 2817528Ssteve.reinhardt@amd.com # By iterating through the constituent members of the vector here 2827528Ssteve.reinhardt@amd.com # we can nicely handle iterating over all a SimObject's children 2837528Ssteve.reinhardt@amd.com # without having to provide lots of special functions on 2847528Ssteve.reinhardt@amd.com # SimObjectVector directly. 2857528Ssteve.reinhardt@amd.com def descendants(self): 2867528Ssteve.reinhardt@amd.com for v in self: 2873101Sstever@eecs.umich.edu for obj in v.descendants(): 2888664SAli.Saidi@ARM.com yield obj 2898664SAli.Saidi@ARM.com 2908664SAli.Saidi@ARM.com def get_config_as_dict(self): 2918664SAli.Saidi@ARM.com a = [] 2928664SAli.Saidi@ARM.com for v in self: 2938664SAli.Saidi@ARM.com a.append(v.get_config_as_dict()) 2949953Sgeoffrey.blake@arm.com return a 2959953Sgeoffrey.blake@arm.com 2969953Sgeoffrey.blake@arm.com # If we are replacing an item in the vector, make sure to set the 2979953Sgeoffrey.blake@arm.com # parent reference of the new SimObject to be the same as the parent 2989953Sgeoffrey.blake@arm.com # of the SimObject being replaced. Useful to have if we created 2999953Sgeoffrey.blake@arm.com # a SimObjectVector of temporary objects that will be modified later in 3009953Sgeoffrey.blake@arm.com # configuration scripts. 3019953Sgeoffrey.blake@arm.com def __setitem__(self, key, value): 3029953Sgeoffrey.blake@arm.com val = self[key] 3039953Sgeoffrey.blake@arm.com if value.has_parent(): 3049953Sgeoffrey.blake@arm.com warn("SimObject %s already has a parent" % value.get_name() +\ 3059953Sgeoffrey.blake@arm.com " that is being overwritten by a SimObjectVector") 3069953Sgeoffrey.blake@arm.com value.set_parent(val.get_parent(), val._name) 30710267SGeoffrey.Blake@arm.com super(SimObjectVector, self).__setitem__(key, value) 30810267SGeoffrey.Blake@arm.com 30910267SGeoffrey.Blake@arm.com # Enumerate the params of each member of the SimObject vector. Creates 31010267SGeoffrey.Blake@arm.com # strings that will allow indexing into the vector by the python code and 31110267SGeoffrey.Blake@arm.com # allow it to be specified on the command line. 31210267SGeoffrey.Blake@arm.com def enumerateParams(self, flags_dict = {}, 31310267SGeoffrey.Blake@arm.com cmd_line_str = "", 31410267SGeoffrey.Blake@arm.com access_str = ""): 31510267SGeoffrey.Blake@arm.com if hasattr(self, "_paramEnumed"): 31610267SGeoffrey.Blake@arm.com print("Cycle detected enumerating params at %s?!" % (cmd_line_str)) 31710267SGeoffrey.Blake@arm.com else: 31810267SGeoffrey.Blake@arm.com x = 0 31910267SGeoffrey.Blake@arm.com for vals in self: 32010267SGeoffrey.Blake@arm.com # Each entry in the SimObjectVector should be an 32110267SGeoffrey.Blake@arm.com # instance of a SimObject 32210267SGeoffrey.Blake@arm.com flags_dict = vals.enumerateParams(flags_dict, 32310267SGeoffrey.Blake@arm.com cmd_line_str + "%d." % x, 32410267SGeoffrey.Blake@arm.com access_str + "[%d]." % x) 32510267SGeoffrey.Blake@arm.com x = x + 1 32610267SGeoffrey.Blake@arm.com 3273101Sstever@eecs.umich.edu return flags_dict 3283101Sstever@eecs.umich.edu 3293101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc): 3303101Sstever@eecs.umich.edu # Convert assigned value to appropriate type. If the RHS is not a 3313101Sstever@eecs.umich.edu # list or tuple, it generates a single-element list. 3323101Sstever@eecs.umich.edu def convert(self, value): 3333101Sstever@eecs.umich.edu if isinstance(value, (list, tuple)): 33410364SGeoffrey.Blake@arm.com # list: coerce each element into new list 33510364SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) for v in value ] 33610364SGeoffrey.Blake@arm.com elif isinstance(value, str): 33710364SGeoffrey.Blake@arm.com # If input is a csv string 3383101Sstever@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) \ 3394762Snate@binkert.org for v in value.strip('[').strip(']').split(',') ] 3404762Snate@binkert.org else: 3414762Snate@binkert.org # singleton: coerce to a single-element list 3424762Snate@binkert.org tmp_list = [ ParamDesc.convert(self, value) ] 3437528Ssteve.reinhardt@amd.com 3444762Snate@binkert.org if isSimObjectSequence(tmp_list): 3454762Snate@binkert.org return SimObjectVector(tmp_list) 3464762Snate@binkert.org else: 34710267SGeoffrey.Blake@arm.com return VectorParamValue(tmp_list) 34810267SGeoffrey.Blake@arm.com 34910267SGeoffrey.Blake@arm.com # Produce a human readable example string that describes 35010267SGeoffrey.Blake@arm.com # how to set this vector parameter in the absence of a default 35110267SGeoffrey.Blake@arm.com # value. 35210267SGeoffrey.Blake@arm.com def example_str(self): 35310267SGeoffrey.Blake@arm.com s = super(VectorParamDesc, self).example_str() 35410267SGeoffrey.Blake@arm.com help_str = "[" + s + "," + s + ", ...]" 35510267SGeoffrey.Blake@arm.com return help_str 35610267SGeoffrey.Blake@arm.com 35710267SGeoffrey.Blake@arm.com # Produce a human readable representation of the value of this vector param. 35810267SGeoffrey.Blake@arm.com def pretty_print(self, value): 35910267SGeoffrey.Blake@arm.com if isinstance(value, (list, tuple)): 36010267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ] 36110267SGeoffrey.Blake@arm.com elif isinstance(value, str): 36210267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ] 36310267SGeoffrey.Blake@arm.com else: 36410267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, value) ] 36510267SGeoffrey.Blake@arm.com 36610267SGeoffrey.Blake@arm.com return tmp_list 36710267SGeoffrey.Blake@arm.com 36810267SGeoffrey.Blake@arm.com # This is a helper function for the new config system 36910267SGeoffrey.Blake@arm.com def __call__(self, value): 37010267SGeoffrey.Blake@arm.com if isinstance(value, (list, tuple)): 37110267SGeoffrey.Blake@arm.com # list: coerce each element into new list 37210267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) for v in value ] 37310364SGeoffrey.Blake@arm.com elif isinstance(value, str): 37410364SGeoffrey.Blake@arm.com # If input is a csv string 37510267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) \ 37610267SGeoffrey.Blake@arm.com for v in value.strip('[').strip(']').split(',') ] 37710267SGeoffrey.Blake@arm.com else: 37810267SGeoffrey.Blake@arm.com # singleton: coerce to a single-element list 37910267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, value) ] 38010267SGeoffrey.Blake@arm.com 3817673Snate@binkert.org return VectorParamValue(tmp_list) 3827673Snate@binkert.org 3837673Snate@binkert.org def cxx_predecls(self, code): 3843101Sstever@eecs.umich.edu code('#include <vector>') 38511988Sandreas.sandberg@arm.com self.ptype.cxx_predecls(code) 38611988Sandreas.sandberg@arm.com 38711988Sandreas.sandberg@arm.com def pybind_predecls(self, code): 38811988Sandreas.sandberg@arm.com code('#include <vector>') 3897673Snate@binkert.org self.ptype.pybind_predecls(code) 3907673Snate@binkert.org 3913101Sstever@eecs.umich.edu def cxx_decl(self, code): 3923101Sstever@eecs.umich.edu code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};') 3933101Sstever@eecs.umich.edu 3943101Sstever@eecs.umich.educlass ParamFactory(object): 3953101Sstever@eecs.umich.edu def __init__(self, param_desc_class, ptype_str = None): 3963101Sstever@eecs.umich.edu self.param_desc_class = param_desc_class 3973101Sstever@eecs.umich.edu self.ptype_str = ptype_str 3983101Sstever@eecs.umich.edu 3993101Sstever@eecs.umich.edu def __getattr__(self, attr): 4003101Sstever@eecs.umich.edu if self.ptype_str: 4013101Sstever@eecs.umich.edu attr = self.ptype_str + '.' + attr 4023101Sstever@eecs.umich.edu return ParamFactory(self.param_desc_class, attr) 4033101Sstever@eecs.umich.edu 4043101Sstever@eecs.umich.edu # E.g., Param.Int(5, "number of widgets") 4053101Sstever@eecs.umich.edu def __call__(self, *args, **kwargs): 4065033Smilesck@eecs.umich.edu ptype = None 4075033Smilesck@eecs.umich.edu try: 4083101Sstever@eecs.umich.edu ptype = allParams[self.ptype_str] 4093101Sstever@eecs.umich.edu except KeyError: 4103101Sstever@eecs.umich.edu # if name isn't defined yet, assume it's a SimObject, and 4113101Sstever@eecs.umich.edu # try to resolve it later 4123101Sstever@eecs.umich.edu pass 4133101Sstever@eecs.umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 4143101Sstever@eecs.umich.edu 4153101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc) 4163101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc) 4173101Sstever@eecs.umich.edu 4183101Sstever@eecs.umich.edu##################################################################### 4193101Sstever@eecs.umich.edu# 4203101Sstever@eecs.umich.edu# Parameter Types 4213101Sstever@eecs.umich.edu# 4223101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types 4233101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more 4243101Sstever@eecs.umich.edu# flexible to define our own set of types. This gives us more control 4253101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the 4263101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via 4273101Sstever@eecs.umich.edu# the __str__() conversion method). 4283101Sstever@eecs.umich.edu# 4293101Sstever@eecs.umich.edu##################################################################### 4303101Sstever@eecs.umich.edu 4313101Sstever@eecs.umich.edu# String-valued parameter. Just mixin the ParamValue class with the 4323101Sstever@eecs.umich.edu# built-in str class. 43310267SGeoffrey.Blake@arm.comclass String(ParamValue,str): 4347673Snate@binkert.org cxx_type = 'std::string' 4357673Snate@binkert.org cmd_line_settable = True 4367673Snate@binkert.org 4377673Snate@binkert.org @classmethod 4387673Snate@binkert.org def cxx_predecls(self, code): 43910267SGeoffrey.Blake@arm.com code('#include <string>') 44010267SGeoffrey.Blake@arm.com 44110267SGeoffrey.Blake@arm.com def __call__(self, value): 44210267SGeoffrey.Blake@arm.com self = value 44310458Sandreas.hansson@arm.com return value 44410458Sandreas.hansson@arm.com 44510458Sandreas.hansson@arm.com @classmethod 44610458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 44710458Sandreas.hansson@arm.com code('%s = %s;' % (dest, src)) 4484762Snate@binkert.org code('%s true;' % ret) 4494762Snate@binkert.org 4503101Sstever@eecs.umich.edu def getValue(self): 4513101Sstever@eecs.umich.edu return self 4523101Sstever@eecs.umich.edu 4533101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math 4543101Sstever@eecs.umich.edu# operations in a type-safe way. e.g., a Latency times an int returns 4553101Sstever@eecs.umich.edu# a new Latency object. 4563101Sstever@eecs.umich.educlass NumericParamValue(ParamValue): 4573101Sstever@eecs.umich.edu @staticmethod 4583101Sstever@eecs.umich.edu def unwrap(v): 4593101Sstever@eecs.umich.edu return v.value if isinstance(v, NumericParamValue) else v 4603101Sstever@eecs.umich.edu 4613714Sstever@eecs.umich.edu def __str__(self): 4623714Sstever@eecs.umich.edu return str(self.value) 4633714Sstever@eecs.umich.edu 4643714Sstever@eecs.umich.edu def __float__(self): 4653714Sstever@eecs.umich.edu return float(self.value) 4663714Sstever@eecs.umich.edu 4673101Sstever@eecs.umich.edu def __long__(self): 4683101Sstever@eecs.umich.edu return long(self.value) 4693101Sstever@eecs.umich.edu 4703101Sstever@eecs.umich.edu def __int__(self): 4713101Sstever@eecs.umich.edu return int(self.value) 4723101Sstever@eecs.umich.edu 4733101Sstever@eecs.umich.edu # hook for bounds checking 4743101Sstever@eecs.umich.edu def _check(self): 4753101Sstever@eecs.umich.edu return 4763101Sstever@eecs.umich.edu 4773101Sstever@eecs.umich.edu def __mul__(self, other): 4783101Sstever@eecs.umich.edu newobj = self.__class__(self) 4793101Sstever@eecs.umich.edu newobj.value *= NumericParamValue.unwrap(other) 4803101Sstever@eecs.umich.edu newobj._check() 4813101Sstever@eecs.umich.edu return newobj 4823101Sstever@eecs.umich.edu 4833101Sstever@eecs.umich.edu __rmul__ = __mul__ 4843101Sstever@eecs.umich.edu 4853101Sstever@eecs.umich.edu def __truediv__(self, other): 4863101Sstever@eecs.umich.edu newobj = self.__class__(self) 4873101Sstever@eecs.umich.edu newobj.value /= NumericParamValue.unwrap(other) 4883101Sstever@eecs.umich.edu newobj._check() 4893101Sstever@eecs.umich.edu return newobj 4903101Sstever@eecs.umich.edu 49110380SAndrew.Bardsley@arm.com def __floordiv__(self, other): 49210380SAndrew.Bardsley@arm.com newobj = self.__class__(self) 49310380SAndrew.Bardsley@arm.com newobj.value //= NumericParamValue.unwrap(other) 49410458Sandreas.hansson@arm.com newobj._check() 49510458Sandreas.hansson@arm.com return newobj 49610458Sandreas.hansson@arm.com 49710458Sandreas.hansson@arm.com 49810458Sandreas.hansson@arm.com def __add__(self, other): 49910458Sandreas.hansson@arm.com newobj = self.__class__(self) 50010458Sandreas.hansson@arm.com newobj.value += NumericParamValue.unwrap(other) 50110458Sandreas.hansson@arm.com newobj._check() 50210458Sandreas.hansson@arm.com return newobj 50310458Sandreas.hansson@arm.com 50410458Sandreas.hansson@arm.com def __sub__(self, other): 50510458Sandreas.hansson@arm.com newobj = self.__class__(self) 50610458Sandreas.hansson@arm.com newobj.value -= NumericParamValue.unwrap(other) 5073101Sstever@eecs.umich.edu newobj._check() 5085033Smilesck@eecs.umich.edu return newobj 5093101Sstever@eecs.umich.edu 5103101Sstever@eecs.umich.edu def __iadd__(self, other): 5113101Sstever@eecs.umich.edu self.value += NumericParamValue.unwrap(other) 5123101Sstever@eecs.umich.edu self._check() 5133101Sstever@eecs.umich.edu return self 5143101Sstever@eecs.umich.edu 5153101Sstever@eecs.umich.edu def __isub__(self, other): 5163101Sstever@eecs.umich.edu self.value -= NumericParamValue.unwrap(other) 5173101Sstever@eecs.umich.edu self._check() 5183101Sstever@eecs.umich.edu return self 5193101Sstever@eecs.umich.edu 5203101Sstever@eecs.umich.edu def __imul__(self, other): 5215822Ssaidi@eecs.umich.edu self.value *= NumericParamValue.unwrap(other) 5225822Ssaidi@eecs.umich.edu self._check() 5233101Sstever@eecs.umich.edu return self 5243101Sstever@eecs.umich.edu 5253101Sstever@eecs.umich.edu def __itruediv__(self, other): 5263101Sstever@eecs.umich.edu self.value /= NumericParamValue.unwrap(other) 5273101Sstever@eecs.umich.edu self._check() 5283101Sstever@eecs.umich.edu return self 5293101Sstever@eecs.umich.edu 5303101Sstever@eecs.umich.edu def __ifloordiv__(self, other): 5313101Sstever@eecs.umich.edu self.value //= NumericParamValue.unwrap(other) 5323101Sstever@eecs.umich.edu self._check() 5333101Sstever@eecs.umich.edu return self 5343101Sstever@eecs.umich.edu 5353101Sstever@eecs.umich.edu def __lt__(self, other): 53610267SGeoffrey.Blake@arm.com return self.value < NumericParamValue.unwrap(other) 5373101Sstever@eecs.umich.edu 5383101Sstever@eecs.umich.edu # Python 2.7 pre __future__.division operators 5393101Sstever@eecs.umich.edu # TODO: Remove these when after "import division from __future__" 5403101Sstever@eecs.umich.edu __div__ = __truediv__ 5413101Sstever@eecs.umich.edu __idiv__ = __itruediv__ 5423101Sstever@eecs.umich.edu 5433101Sstever@eecs.umich.edu def config_value(self): 5443101Sstever@eecs.umich.edu return self.value 5453102Sstever@eecs.umich.edu 5463714Sstever@eecs.umich.edu @classmethod 5473101Sstever@eecs.umich.edu def cxx_ini_predecls(cls, code): 5483714Sstever@eecs.umich.edu # Assume that base/str.hh will be included anyway 5493714Sstever@eecs.umich.edu # code('#include "base/str.hh"') 5503714Sstever@eecs.umich.edu pass 5513101Sstever@eecs.umich.edu 5523101Sstever@eecs.umich.edu # The default for parsing PODs from an .ini entry is to extract from an 55310267SGeoffrey.Blake@arm.com # istringstream and let overloading choose the right type according to 55410267SGeoffrey.Blake@arm.com # the dest type. 55510267SGeoffrey.Blake@arm.com @classmethod 55610267SGeoffrey.Blake@arm.com def cxx_ini_parse(self, code, src, dest, ret): 5577673Snate@binkert.org code('%s to_number(%s, %s);' % (ret, src, dest)) 5587673Snate@binkert.org 5597673Snate@binkert.org# Metaclass for bounds-checked integer parameters. See CheckedInt. 5607673Snate@binkert.orgclass CheckedIntType(MetaParamValue): 5617673Snate@binkert.org def __init__(cls, name, bases, dict): 5624762Snate@binkert.org super(CheckedIntType, cls).__init__(name, bases, dict) 5634762Snate@binkert.org 5644762Snate@binkert.org # CheckedInt is an abstract base class, so we actually don't 5653101Sstever@eecs.umich.edu # want to do any processing on it... the rest of this code is 5663101Sstever@eecs.umich.edu # just for classes that derive from CheckedInt. 5673101Sstever@eecs.umich.edu if name == 'CheckedInt': 5683101Sstever@eecs.umich.edu return 5693101Sstever@eecs.umich.edu 5703101Sstever@eecs.umich.edu if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 5713101Sstever@eecs.umich.edu if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 5723101Sstever@eecs.umich.edu panic("CheckedInt subclass %s must define either\n" \ 5733101Sstever@eecs.umich.edu " 'min' and 'max' or 'size' and 'unsigned'\n", 5743101Sstever@eecs.umich.edu name); 5753101Sstever@eecs.umich.edu if cls.unsigned: 5763101Sstever@eecs.umich.edu cls.min = 0 5773101Sstever@eecs.umich.edu cls.max = 2 ** cls.size - 1 5783101Sstever@eecs.umich.edu else: 5793101Sstever@eecs.umich.edu cls.min = -(2 ** (cls.size - 1)) 5803101Sstever@eecs.umich.edu cls.max = (2 ** (cls.size - 1)) - 1 5813101Sstever@eecs.umich.edu 5823101Sstever@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters. This 5833101Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific 5849184Sandreas.hansson@arm.com# bounds. Initialization of the min and max bounds is done in the 5859184Sandreas.hansson@arm.com# metaclass CheckedIntType.__init__. 5869184Sandreas.hansson@arm.comclass CheckedInt(NumericParamValue): 5879184Sandreas.hansson@arm.com __metaclass__ = CheckedIntType 5889184Sandreas.hansson@arm.com cmd_line_settable = True 5899184Sandreas.hansson@arm.com 59011802Sandreas.sandberg@arm.com def _check(self): 5919184Sandreas.hansson@arm.com if not self.min <= self.value <= self.max: 5929184Sandreas.hansson@arm.com raise TypeError('Integer param out of bounds %d < %d < %d' % \ 59310458Sandreas.hansson@arm.com (self.min, self.value, self.max)) 59410458Sandreas.hansson@arm.com 59510458Sandreas.hansson@arm.com def __init__(self, value): 59610458Sandreas.hansson@arm.com if isinstance(value, str): 59710458Sandreas.hansson@arm.com self.value = convert.toInteger(value) 59810458Sandreas.hansson@arm.com elif isinstance(value, (int, long, float, NumericParamValue)): 59910458Sandreas.hansson@arm.com self.value = long(value) 60010458Sandreas.hansson@arm.com else: 60110458Sandreas.hansson@arm.com raise TypeError("Can't convert object of type %s to CheckedInt" \ 60210458Sandreas.hansson@arm.com % type(value).__name__) 60310458Sandreas.hansson@arm.com self._check() 60410458Sandreas.hansson@arm.com 60510458Sandreas.hansson@arm.com def __call__(self, value): 60610458Sandreas.hansson@arm.com self.__init__(value) 6073101Sstever@eecs.umich.edu return value 6084446Sbinkertn@umich.edu 60910668SGeoffrey.Blake@arm.com def __index__(self): 6103101Sstever@eecs.umich.edu return int(self.value) 6115468Snate@binkert.org 61210267SGeoffrey.Blake@arm.com @classmethod 6135468Snate@binkert.org def cxx_predecls(cls, code): 6145468Snate@binkert.org # most derived types require this, so we just do it here once 6155468Snate@binkert.org code('#include "base/types.hh"') 6165468Snate@binkert.org 6175468Snate@binkert.org def getValue(self): 61810267SGeoffrey.Blake@arm.com return long(self.value) 61910267SGeoffrey.Blake@arm.com 62010267SGeoffrey.Blake@arm.comclass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 62110267SGeoffrey.Blake@arm.comclass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 6224762Snate@binkert.org 6234762Snate@binkert.orgclass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 6244762Snate@binkert.orgclass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 62510380SAndrew.Bardsley@arm.comclass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 62610380SAndrew.Bardsley@arm.comclass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 62710380SAndrew.Bardsley@arm.comclass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 62810458Sandreas.hansson@arm.comclass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 62910458Sandreas.hansson@arm.comclass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 63010458Sandreas.hansson@arm.comclass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 63110458Sandreas.hansson@arm.com 63210458Sandreas.hansson@arm.comclass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 63310458Sandreas.hansson@arm.comclass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 63410458Sandreas.hansson@arm.comclass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 63510458Sandreas.hansson@arm.comclass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 6363101Sstever@eecs.umich.edu 6373101Sstever@eecs.umich.educlass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 63810267SGeoffrey.Blake@arm.com 6393101Sstever@eecs.umich.educlass Cycles(CheckedInt): 6403101Sstever@eecs.umich.edu cxx_type = 'Cycles' 6413101Sstever@eecs.umich.edu size = 64 6423101Sstever@eecs.umich.edu unsigned = True 6433101Sstever@eecs.umich.edu 6443101Sstever@eecs.umich.edu def getValue(self): 6453102Sstever@eecs.umich.edu from _m5.core import Cycles 6463101Sstever@eecs.umich.edu return Cycles(self.value) 6473101Sstever@eecs.umich.edu 6483101Sstever@eecs.umich.edu @classmethod 6494168Sbinkertn@umich.edu def cxx_ini_predecls(cls, code): 65010267SGeoffrey.Blake@arm.com # Assume that base/str.hh will be included anyway 6513101Sstever@eecs.umich.edu # code('#include "base/str.hh"') 6523101Sstever@eecs.umich.edu pass 6533101Sstever@eecs.umich.edu 6543101Sstever@eecs.umich.edu @classmethod 6553101Sstever@eecs.umich.edu def cxx_ini_parse(cls, code, src, dest, ret): 6563101Sstever@eecs.umich.edu code('uint64_t _temp;') 6573102Sstever@eecs.umich.edu code('bool _ret = to_number(%s, _temp);' % src) 6583101Sstever@eecs.umich.edu code('if (_ret)') 6593101Sstever@eecs.umich.edu code(' %s = Cycles(_temp);' % dest) 6603101Sstever@eecs.umich.edu code('%s _ret;' % ret) 6613101Sstever@eecs.umich.edu 6623101Sstever@eecs.umich.educlass Float(ParamValue, float): 6633101Sstever@eecs.umich.edu cxx_type = 'double' 6643101Sstever@eecs.umich.edu cmd_line_settable = True 6653101Sstever@eecs.umich.edu 6663101Sstever@eecs.umich.edu def __init__(self, value): 6673101Sstever@eecs.umich.edu if isinstance(value, (int, long, float, NumericParamValue, Float, str)): 6683101Sstever@eecs.umich.edu self.value = float(value) 66910317Smitch.hayenga@arm.com else: 67010317Smitch.hayenga@arm.com raise TypeError("Can't convert object of type %s to Float" \ 67110317Smitch.hayenga@arm.com % type(value).__name__) 67210317Smitch.hayenga@arm.com 67310317Smitch.hayenga@arm.com def __call__(self, value): 6743102Sstever@eecs.umich.edu self.__init__(value) 67510317Smitch.hayenga@arm.com return value 67610317Smitch.hayenga@arm.com 67710317Smitch.hayenga@arm.com def getValue(self): 67810317Smitch.hayenga@arm.com return float(self.value) 67910317Smitch.hayenga@arm.com 6803101Sstever@eecs.umich.edu def config_value(self): 6813584Ssaidi@eecs.umich.edu return self 6823584Ssaidi@eecs.umich.edu 6833584Ssaidi@eecs.umich.edu @classmethod 6843584Ssaidi@eecs.umich.edu def cxx_ini_predecls(cls, code): 6853584Ssaidi@eecs.umich.edu code('#include <sstream>') 68610267SGeoffrey.Blake@arm.com 68710267SGeoffrey.Blake@arm.com @classmethod 68810267SGeoffrey.Blake@arm.com def cxx_ini_parse(self, code, src, dest, ret): 68910267SGeoffrey.Blake@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 69010267SGeoffrey.Blake@arm.com 69110267SGeoffrey.Blake@arm.comclass MemorySize(CheckedInt): 6923101Sstever@eecs.umich.edu cxx_type = 'uint64_t' 6939232Sandreas.hansson@arm.com ex_str = '512MB' 6949235Sandreas.hansson@arm.com size = 64 6953101Sstever@eecs.umich.edu unsigned = True 6963101Sstever@eecs.umich.edu def __init__(self, value): 69710676Sandreas.hansson@arm.com if isinstance(value, MemorySize): 6989411Sandreas.hansson@arm.com self.value = value.value 69910676Sandreas.hansson@arm.com else: 7009411Sandreas.hansson@arm.com self.value = convert.toMemorySize(value) 7019411Sandreas.hansson@arm.com self._check() 7029411Sandreas.hansson@arm.com 7033101Sstever@eecs.umich.educlass MemorySize32(CheckedInt): 7049411Sandreas.hansson@arm.com cxx_type = 'uint32_t' 7059411Sandreas.hansson@arm.com ex_str = '512MB' 7069411Sandreas.hansson@arm.com size = 32 7073101Sstever@eecs.umich.edu unsigned = True 7089232Sandreas.hansson@arm.com def __init__(self, value): 7093101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 7109232Sandreas.hansson@arm.com self.value = value.value 7113101Sstever@eecs.umich.edu else: 7123101Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 7133101Sstever@eecs.umich.edu self._check() 7149411Sandreas.hansson@arm.com 7159411Sandreas.hansson@arm.comclass Addr(CheckedInt): 7169411Sandreas.hansson@arm.com cxx_type = 'Addr' 71710676Sandreas.hansson@arm.com size = 64 71810676Sandreas.hansson@arm.com unsigned = True 7199411Sandreas.hansson@arm.com def __init__(self, value): 7209411Sandreas.hansson@arm.com if isinstance(value, Addr): 7219411Sandreas.hansson@arm.com self.value = value.value 7229411Sandreas.hansson@arm.com else: 7239411Sandreas.hansson@arm.com try: 7243101Sstever@eecs.umich.edu # Often addresses are referred to with sizes. Ex: A device 7259232Sandreas.hansson@arm.com # base address is at "512MB". Use toMemorySize() to convert 7263101Sstever@eecs.umich.edu # these into addresses. If the address is not specified with a 7273101Sstever@eecs.umich.edu # "size", an exception will occur and numeric translation will 7283101Sstever@eecs.umich.edu # proceed below. 7293101Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 7309232Sandreas.hansson@arm.com except (TypeError, ValueError): 7313101Sstever@eecs.umich.edu # Convert number to string and use long() to do automatic 7325219Ssaidi@eecs.umich.edu # base conversion (requires base=0 for auto-conversion) 7339232Sandreas.hansson@arm.com self.value = long(str(value), base=0) 7349232Sandreas.hansson@arm.com 7353101Sstever@eecs.umich.edu self._check() 7369232Sandreas.hansson@arm.com def __add__(self, other): 7379232Sandreas.hansson@arm.com if isinstance(other, Addr): 7383101Sstever@eecs.umich.edu return self.value + other.value 7393101Sstever@eecs.umich.edu else: 7409232Sandreas.hansson@arm.com return self.value + other 7419232Sandreas.hansson@arm.com def pretty_print(self, value): 7423101Sstever@eecs.umich.edu try: 7433101Sstever@eecs.umich.edu val = convert.toMemorySize(value) 7443101Sstever@eecs.umich.edu except TypeError: 7453101Sstever@eecs.umich.edu val = long(value) 7469232Sandreas.hansson@arm.com return "0x%x" % long(val) 7473101Sstever@eecs.umich.edu 7483101Sstever@eecs.umich.educlass AddrRange(ParamValue): 74911620SMatthew.Poremba@amd.com cxx_type = 'AddrRange' 75011620SMatthew.Poremba@amd.com 75111620SMatthew.Poremba@amd.com def __init__(self, *args, **kwargs): 7529232Sandreas.hansson@arm.com # Disable interleaving and hashing by default 7539232Sandreas.hansson@arm.com self.intlvHighBit = 0 7549411Sandreas.hansson@arm.com self.xorHighBit = 0 7559411Sandreas.hansson@arm.com self.intlvBits = 0 7563101Sstever@eecs.umich.edu self.intlvMatch = 0 7577673Snate@binkert.org 7587673Snate@binkert.org def handle_kwargs(self, kwargs): 7599232Sandreas.hansson@arm.com # An address range needs to have an upper limit, specified 7609235Sandreas.hansson@arm.com # either explicitly with an end, or as an offset using the 7617675Snate@binkert.org # size keyword. 7627675Snate@binkert.org if 'end' in kwargs: 76311988Sandreas.sandberg@arm.com self.end = Addr(kwargs.pop('end')) 76411988Sandreas.sandberg@arm.com elif 'size' in kwargs: 76511988Sandreas.sandberg@arm.com self.end = self.start + Addr(kwargs.pop('size')) - 1 76611988Sandreas.sandberg@arm.com else: 76711988Sandreas.sandberg@arm.com raise TypeError("Either end or size must be specified") 76810458Sandreas.hansson@arm.com 76910458Sandreas.hansson@arm.com # Now on to the optional bit 77010458Sandreas.hansson@arm.com if 'intlvHighBit' in kwargs: 77110458Sandreas.hansson@arm.com self.intlvHighBit = int(kwargs.pop('intlvHighBit')) 77210458Sandreas.hansson@arm.com if 'xorHighBit' in kwargs: 77311620SMatthew.Poremba@amd.com self.xorHighBit = int(kwargs.pop('xorHighBit')) 77411620SMatthew.Poremba@amd.com if 'intlvBits' in kwargs: 77510458Sandreas.hansson@arm.com self.intlvBits = int(kwargs.pop('intlvBits')) 77610458Sandreas.hansson@arm.com if 'intlvMatch' in kwargs: 77710458Sandreas.hansson@arm.com self.intlvMatch = int(kwargs.pop('intlvMatch')) 77810458Sandreas.hansson@arm.com 77910458Sandreas.hansson@arm.com if len(args) == 0: 78011620SMatthew.Poremba@amd.com self.start = Addr(kwargs.pop('start')) 78111620SMatthew.Poremba@amd.com handle_kwargs(self, kwargs) 78211620SMatthew.Poremba@amd.com 78311620SMatthew.Poremba@amd.com elif len(args) == 1: 78411620SMatthew.Poremba@amd.com if kwargs: 78511620SMatthew.Poremba@amd.com self.start = Addr(args[0]) 78611620SMatthew.Poremba@amd.com handle_kwargs(self, kwargs) 78711620SMatthew.Poremba@amd.com elif isinstance(args[0], (list, tuple)): 78811620SMatthew.Poremba@amd.com self.start = Addr(args[0][0]) 78911620SMatthew.Poremba@amd.com self.end = Addr(args[0][1]) 79010458Sandreas.hansson@arm.com else: 79110458Sandreas.hansson@arm.com self.start = Addr(0) 79210458Sandreas.hansson@arm.com self.end = Addr(args[0]) - 1 79311620SMatthew.Poremba@amd.com 79411620SMatthew.Poremba@amd.com elif len(args) == 2: 79510458Sandreas.hansson@arm.com self.start = Addr(args[0]) 79610458Sandreas.hansson@arm.com self.end = Addr(args[1]) 7974762Snate@binkert.org else: 79811991Sandreas.sandberg@arm.com raise TypeError("Too many arguments specified") 79911802Sandreas.sandberg@arm.com 8004762Snate@binkert.org if kwargs: 8019411Sandreas.hansson@arm.com raise TypeError("Too many keywords: %s" % list(kwargs.keys())) 80210676Sandreas.hansson@arm.com 80310676Sandreas.hansson@arm.com def __str__(self): 8043101Sstever@eecs.umich.edu return '%s:%s:%s:%s:%s:%s' \ 8053101Sstever@eecs.umich.edu % (self.start, self.end, self.intlvHighBit, self.xorHighBit,\ 8063101Sstever@eecs.umich.edu self.intlvBits, self.intlvMatch) 8073101Sstever@eecs.umich.edu 8083101Sstever@eecs.umich.edu def size(self): 8093101Sstever@eecs.umich.edu # Divide the size by the size of the interleaving slice 81010267SGeoffrey.Blake@arm.com return (long(self.end) - long(self.start) + 1) >> self.intlvBits 81110267SGeoffrey.Blake@arm.com 8123101Sstever@eecs.umich.edu @classmethod 8133101Sstever@eecs.umich.edu def cxx_predecls(cls, code): 8143102Sstever@eecs.umich.edu Addr.cxx_predecls(code) 8153101Sstever@eecs.umich.edu code('#include "base/addr_range.hh"') 8163101Sstever@eecs.umich.edu 8173101Sstever@eecs.umich.edu @classmethod 81810267SGeoffrey.Blake@arm.com def pybind_predecls(cls, code): 81910267SGeoffrey.Blake@arm.com Addr.pybind_predecls(code) 82010267SGeoffrey.Blake@arm.com code('#include "base/addr_range.hh"') 82110267SGeoffrey.Blake@arm.com 8224762Snate@binkert.org @classmethod 8234762Snate@binkert.org def cxx_ini_predecls(cls, code): 8244762Snate@binkert.org code('#include <sstream>') 8253101Sstever@eecs.umich.edu 8263101Sstever@eecs.umich.edu @classmethod 8273101Sstever@eecs.umich.edu def cxx_ini_parse(cls, code, src, dest, ret): 8288934SBrad.Beckmann@amd.com code('uint64_t _start, _end, _intlvHighBit = 0, _xorHighBit = 0;') 8298934SBrad.Beckmann@amd.com code('uint64_t _intlvBits = 0, _intlvMatch = 0;') 8308934SBrad.Beckmann@amd.com code('char _sep;') 8318934SBrad.Beckmann@amd.com code('std::istringstream _stream(${src});') 8328934SBrad.Beckmann@amd.com code('_stream >> _start;') 8333101Sstever@eecs.umich.edu code('_stream.get(_sep);') 8343101Sstever@eecs.umich.edu code('_stream >> _end;') 8353101Sstever@eecs.umich.edu code('if (!_stream.fail() && !_stream.eof()) {') 8363101Sstever@eecs.umich.edu code(' _stream.get(_sep);') 8373101Sstever@eecs.umich.edu code(' _stream >> _intlvHighBit;') 83810380SAndrew.Bardsley@arm.com code(' _stream.get(_sep);') 83910380SAndrew.Bardsley@arm.com code(' _stream >> _xorHighBit;') 84010380SAndrew.Bardsley@arm.com code(' _stream.get(_sep);') 84110458Sandreas.hansson@arm.com code(' _stream >> _intlvBits;') 84210458Sandreas.hansson@arm.com code(' _stream.get(_sep);') 84310458Sandreas.hansson@arm.com code(' _stream >> _intlvMatch;') 84410458Sandreas.hansson@arm.com code('}') 84510458Sandreas.hansson@arm.com code('bool _ret = !_stream.fail() &&' 84610458Sandreas.hansson@arm.com '_stream.eof() && _sep == \':\';') 84710458Sandreas.hansson@arm.com code('if (_ret)') 84810458Sandreas.hansson@arm.com code(' ${dest} = AddrRange(_start, _end, _intlvHighBit, \ 84910458Sandreas.hansson@arm.com _xorHighBit, _intlvBits, _intlvMatch);') 85010458Sandreas.hansson@arm.com code('${ret} _ret;') 8513101Sstever@eecs.umich.edu 8523101Sstever@eecs.umich.edu def getValue(self): 8533101Sstever@eecs.umich.edu # Go from the Python class to the wrapped C++ class 8543101Sstever@eecs.umich.edu from _m5.range import AddrRange 8553101Sstever@eecs.umich.edu 8563101Sstever@eecs.umich.edu return AddrRange(long(self.start), long(self.end), 8573101Sstever@eecs.umich.edu int(self.intlvHighBit), int(self.xorHighBit), 8583101Sstever@eecs.umich.edu int(self.intlvBits), int(self.intlvMatch)) 8593101Sstever@eecs.umich.edu 8603101Sstever@eecs.umich.edu# Boolean parameter type. Python doesn't let you subclass bool, since 8613101Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and 8623101Sstever@eecs.umich.edu# False. Thus this is a little more complicated than String. 8634380Sbinkertn@umich.educlass Bool(ParamValue): 8644380Sbinkertn@umich.edu cxx_type = 'bool' 8654380Sbinkertn@umich.edu cmd_line_settable = True 8663101Sstever@eecs.umich.edu 8674380Sbinkertn@umich.edu def __init__(self, value): 8684380Sbinkertn@umich.edu try: 8694380Sbinkertn@umich.edu self.value = convert.toBool(value) 8703101Sstever@eecs.umich.edu except TypeError: 8713101Sstever@eecs.umich.edu self.value = bool(value) 8723101Sstever@eecs.umich.edu 87310267SGeoffrey.Blake@arm.com def __call__(self, value): 87410267SGeoffrey.Blake@arm.com self.__init__(value) 8757673Snate@binkert.org return value 8767673Snate@binkert.org 8777673Snate@binkert.org def getValue(self): 8787673Snate@binkert.org return bool(self.value) 8797673Snate@binkert.org 8803101Sstever@eecs.umich.edu def __str__(self): 8813101Sstever@eecs.umich.edu return str(self.value) 8823101Sstever@eecs.umich.edu 8833101Sstever@eecs.umich.edu # implement truth value testing for Bool parameters so that these params 8843101Sstever@eecs.umich.edu # evaluate correctly during the python configuration phase 8853101Sstever@eecs.umich.edu def __bool__(self): 8863101Sstever@eecs.umich.edu return bool(self.value) 8873101Sstever@eecs.umich.edu 8883101Sstever@eecs.umich.edu # Python 2.7 uses __nonzero__ instead of __bool__ 8893101Sstever@eecs.umich.edu __nonzero__ = __bool__ 8903101Sstever@eecs.umich.edu 8913101Sstever@eecs.umich.edu def ini_str(self): 8923101Sstever@eecs.umich.edu if self.value: 8939941SGeoffrey.Blake@arm.com return 'true' 8943101Sstever@eecs.umich.edu return 'false' 8953101Sstever@eecs.umich.edu 8963101Sstever@eecs.umich.edu def config_value(self): 8973101Sstever@eecs.umich.edu return self.value 89810267SGeoffrey.Blake@arm.com 89910267SGeoffrey.Blake@arm.com @classmethod 90010267SGeoffrey.Blake@arm.com def cxx_ini_predecls(cls, code): 90110267SGeoffrey.Blake@arm.com # Assume that base/str.hh will be included anyway 9023101Sstever@eecs.umich.edu # code('#include "base/str.hh"') 9033101Sstever@eecs.umich.edu pass 9044380Sbinkertn@umich.edu 9053101Sstever@eecs.umich.edu @classmethod 9063101Sstever@eecs.umich.edu def cxx_ini_parse(cls, code, src, dest, ret): 9074762Snate@binkert.org code('%s to_bool(%s, %s);' % (ret, src, dest)) 90811988Sandreas.sandberg@arm.com 9094762Snate@binkert.orgdef IncEthernetAddr(addr, val = 1): 9104762Snate@binkert.org bytes = [ int(x, 16) for x in addr.split(':') ] 91111228SAndrew.Bardsley@arm.com bytes[5] += val 91211228SAndrew.Bardsley@arm.com for i in (5, 4, 3, 2, 1): 91311228SAndrew.Bardsley@arm.com val,rem = divmod(bytes[i], 256) 9144380Sbinkertn@umich.edu bytes[i] = rem 9154380Sbinkertn@umich.edu if val == 0: 9163101Sstever@eecs.umich.edu break 91710458Sandreas.hansson@arm.com bytes[i - 1] += val 91810458Sandreas.hansson@arm.com assert(bytes[0] <= 255) 91910458Sandreas.hansson@arm.com return ':'.join(map(lambda x: '%02x' % x, bytes)) 92010458Sandreas.hansson@arm.com 92110458Sandreas.hansson@arm.com_NextEthernetAddr = "00:90:00:00:00:01" 9227777Sgblack@eecs.umich.edudef NextEthernetAddr(): 9237777Sgblack@eecs.umich.edu global _NextEthernetAddr 9247777Sgblack@eecs.umich.edu 9257777Sgblack@eecs.umich.edu value = _NextEthernetAddr 92610267SGeoffrey.Blake@arm.com _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 92710267SGeoffrey.Blake@arm.com return value 9287777Sgblack@eecs.umich.edu 9297777Sgblack@eecs.umich.educlass EthernetAddr(ParamValue): 9307777Sgblack@eecs.umich.edu cxx_type = 'Net::EthAddr' 9317777Sgblack@eecs.umich.edu ex_str = "00:90:00:00:00:01" 9327777Sgblack@eecs.umich.edu cmd_line_settable = True 9337777Sgblack@eecs.umich.edu 9347777Sgblack@eecs.umich.edu @classmethod 9357777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 9367777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 9377777Sgblack@eecs.umich.edu 9387777Sgblack@eecs.umich.edu def __init__(self, value): 9397777Sgblack@eecs.umich.edu if value == NextEthernetAddr: 9407777Sgblack@eecs.umich.edu self.value = value 9417777Sgblack@eecs.umich.edu return 9427777Sgblack@eecs.umich.edu 94310267SGeoffrey.Blake@arm.com if not isinstance(value, str): 94410267SGeoffrey.Blake@arm.com raise TypeError("expected an ethernet address and didn't get one") 94510267SGeoffrey.Blake@arm.com 94610267SGeoffrey.Blake@arm.com bytes = value.split(':') 9478579Ssteve.reinhardt@amd.com if len(bytes) != 6: 9488579Ssteve.reinhardt@amd.com raise TypeError('invalid ethernet address %s' % value) 9498579Ssteve.reinhardt@amd.com 9508579Ssteve.reinhardt@amd.com for byte in bytes: 9518579Ssteve.reinhardt@amd.com if not 0 <= int(byte, base=16) <= 0xff: 9528579Ssteve.reinhardt@amd.com raise TypeError('invalid ethernet address %s' % value) 9538579Ssteve.reinhardt@amd.com 9548579Ssteve.reinhardt@amd.com self.value = value 9558579Ssteve.reinhardt@amd.com 9568579Ssteve.reinhardt@amd.com def __call__(self, value): 9578579Ssteve.reinhardt@amd.com self.__init__(value) 9588579Ssteve.reinhardt@amd.com return value 9598579Ssteve.reinhardt@amd.com 9608579Ssteve.reinhardt@amd.com def unproxy(self, base): 9618579Ssteve.reinhardt@amd.com if self.value == NextEthernetAddr: 9628579Ssteve.reinhardt@amd.com return EthernetAddr(self.value()) 9638579Ssteve.reinhardt@amd.com return self 9648579Ssteve.reinhardt@amd.com 9657777Sgblack@eecs.umich.edu def getValue(self): 9667777Sgblack@eecs.umich.edu from _m5.net import EthAddr 9677798Sgblack@eecs.umich.edu return EthAddr(self.value) 9687777Sgblack@eecs.umich.edu 9697777Sgblack@eecs.umich.edu def __str__(self): 97011988Sandreas.sandberg@arm.com return self.value 9717777Sgblack@eecs.umich.edu 9727777Sgblack@eecs.umich.edu def ini_str(self): 9737777Sgblack@eecs.umich.edu return self.value 9747777Sgblack@eecs.umich.edu 9757777Sgblack@eecs.umich.edu @classmethod 9767777Sgblack@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 9777777Sgblack@eecs.umich.edu code('%s = Net::EthAddr(%s);' % (dest, src)) 97810267SGeoffrey.Blake@arm.com code('%s true;' % ret) 97910267SGeoffrey.Blake@arm.com 9807777Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of 9817777Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP. 9827777Sgblack@eecs.umich.educlass IpAddress(ParamValue): 9837777Sgblack@eecs.umich.edu cxx_type = 'Net::IpAddress' 9847777Sgblack@eecs.umich.edu ex_str = "127.0.0.1" 9857777Sgblack@eecs.umich.edu cmd_line_settable = True 9867777Sgblack@eecs.umich.edu 9877777Sgblack@eecs.umich.edu @classmethod 9887777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 9897777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 9907777Sgblack@eecs.umich.edu 9917777Sgblack@eecs.umich.edu def __init__(self, value): 9927777Sgblack@eecs.umich.edu if isinstance(value, IpAddress): 9937777Sgblack@eecs.umich.edu self.ip = value.ip 9947777Sgblack@eecs.umich.edu else: 9957777Sgblack@eecs.umich.edu try: 9967777Sgblack@eecs.umich.edu self.ip = convert.toIpAddress(value) 9977777Sgblack@eecs.umich.edu except TypeError: 9987777Sgblack@eecs.umich.edu self.ip = long(value) 9997777Sgblack@eecs.umich.edu self.verifyIp() 10007777Sgblack@eecs.umich.edu 10017777Sgblack@eecs.umich.edu def __call__(self, value): 10027777Sgblack@eecs.umich.edu self.__init__(value) 10037777Sgblack@eecs.umich.edu return value 10047777Sgblack@eecs.umich.edu 10057777Sgblack@eecs.umich.edu def __str__(self): 10067777Sgblack@eecs.umich.edu tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)] 10077777Sgblack@eecs.umich.edu return '%d.%d.%d.%d' % tuple(tup) 10087777Sgblack@eecs.umich.edu 10097777Sgblack@eecs.umich.edu def __eq__(self, other): 10107777Sgblack@eecs.umich.edu if isinstance(other, IpAddress): 10117777Sgblack@eecs.umich.edu return self.ip == other.ip 10127777Sgblack@eecs.umich.edu elif isinstance(other, str): 10137777Sgblack@eecs.umich.edu try: 10147777Sgblack@eecs.umich.edu return self.ip == convert.toIpAddress(other) 10157777Sgblack@eecs.umich.edu except: 10167777Sgblack@eecs.umich.edu return False 10177777Sgblack@eecs.umich.edu else: 10187777Sgblack@eecs.umich.edu return self.ip == other 10197777Sgblack@eecs.umich.edu 10207777Sgblack@eecs.umich.edu def __ne__(self, other): 102110267SGeoffrey.Blake@arm.com return not (self == other) 102210267SGeoffrey.Blake@arm.com 102310267SGeoffrey.Blake@arm.com def verifyIp(self): 102410267SGeoffrey.Blake@arm.com if self.ip < 0 or self.ip >= (1 << 32): 10258579Ssteve.reinhardt@amd.com raise TypeError("invalid ip address %#08x" % self.ip) 10268579Ssteve.reinhardt@amd.com 10278579Ssteve.reinhardt@amd.com def getValue(self): 10288579Ssteve.reinhardt@amd.com from _m5.net import IpAddress 10298579Ssteve.reinhardt@amd.com return IpAddress(self.ip) 10308579Ssteve.reinhardt@amd.com 10318579Ssteve.reinhardt@amd.com# When initializing an IpNetmask, pass in an existing IpNetmask, a string of 10328579Ssteve.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 10338579Ssteve.reinhardt@amd.com# positional or keyword arguments. 10348579Ssteve.reinhardt@amd.comclass IpNetmask(IpAddress): 10358579Ssteve.reinhardt@amd.com cxx_type = 'Net::IpNetmask' 10368579Ssteve.reinhardt@amd.com ex_str = "127.0.0.0/24" 10378579Ssteve.reinhardt@amd.com cmd_line_settable = True 10388579Ssteve.reinhardt@amd.com 10397777Sgblack@eecs.umich.edu @classmethod 10407777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 10417777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 10427777Sgblack@eecs.umich.edu 10437777Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 10447777Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 104511988Sandreas.sandberg@arm.com if key in kwargs: 10467777Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 10477777Sgblack@eecs.umich.edu elif elseVal: 10487777Sgblack@eecs.umich.edu setattr(self, key, elseVal) 10497777Sgblack@eecs.umich.edu else: 10507777Sgblack@eecs.umich.edu raise TypeError("No value set for %s" % key) 10517777Sgblack@eecs.umich.edu 105210267SGeoffrey.Blake@arm.com if len(args) == 0: 105310267SGeoffrey.Blake@arm.com handle_kwarg(self, kwargs, 'ip') 10547777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask') 10557777Sgblack@eecs.umich.edu 10567777Sgblack@eecs.umich.edu elif len(args) == 1: 10577777Sgblack@eecs.umich.edu if kwargs: 10587777Sgblack@eecs.umich.edu if not 'ip' in kwargs and not 'netmask' in kwargs: 10597777Sgblack@eecs.umich.edu raise TypeError("Invalid arguments") 10607777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 10617777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask', args[0]) 10627777Sgblack@eecs.umich.edu elif isinstance(args[0], IpNetmask): 10637777Sgblack@eecs.umich.edu self.ip = args[0].ip 10647777Sgblack@eecs.umich.edu self.netmask = args[0].netmask 10657777Sgblack@eecs.umich.edu else: 10667777Sgblack@eecs.umich.edu (self.ip, self.netmask) = convert.toIpNetmask(args[0]) 10677777Sgblack@eecs.umich.edu 10687777Sgblack@eecs.umich.edu elif len(args) == 2: 10697777Sgblack@eecs.umich.edu self.ip = args[0] 10707777Sgblack@eecs.umich.edu self.netmask = args[1] 10717777Sgblack@eecs.umich.edu else: 10727777Sgblack@eecs.umich.edu raise TypeError("Too many arguments specified") 10737777Sgblack@eecs.umich.edu 10747777Sgblack@eecs.umich.edu if kwargs: 10757777Sgblack@eecs.umich.edu raise TypeError("Too many keywords: %s" % list(kwargs.keys())) 10767777Sgblack@eecs.umich.edu 10777777Sgblack@eecs.umich.edu self.verify() 10787777Sgblack@eecs.umich.edu 10797777Sgblack@eecs.umich.edu def __call__(self, value): 10807777Sgblack@eecs.umich.edu self.__init__(value) 10817777Sgblack@eecs.umich.edu return value 10827777Sgblack@eecs.umich.edu 10837777Sgblack@eecs.umich.edu def __str__(self): 10847777Sgblack@eecs.umich.edu return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask) 10857777Sgblack@eecs.umich.edu 10867777Sgblack@eecs.umich.edu def __eq__(self, other): 10877777Sgblack@eecs.umich.edu if isinstance(other, IpNetmask): 10887777Sgblack@eecs.umich.edu return self.ip == other.ip and self.netmask == other.netmask 10897777Sgblack@eecs.umich.edu elif isinstance(other, str): 10907777Sgblack@eecs.umich.edu try: 10917777Sgblack@eecs.umich.edu return (self.ip, self.netmask) == convert.toIpNetmask(other) 10927777Sgblack@eecs.umich.edu except: 10937777Sgblack@eecs.umich.edu return False 10947777Sgblack@eecs.umich.edu else: 109510267SGeoffrey.Blake@arm.com return False 109610267SGeoffrey.Blake@arm.com 109710267SGeoffrey.Blake@arm.com def verify(self): 109810267SGeoffrey.Blake@arm.com self.verifyIp() 10998579Ssteve.reinhardt@amd.com if self.netmask < 0 or self.netmask > 32: 11008579Ssteve.reinhardt@amd.com raise TypeError("invalid netmask %d" % netmask) 11018579Ssteve.reinhardt@amd.com 11028579Ssteve.reinhardt@amd.com def getValue(self): 11038579Ssteve.reinhardt@amd.com from _m5.net import IpNetmask 11048579Ssteve.reinhardt@amd.com return IpNetmask(self.ip, self.netmask) 11058579Ssteve.reinhardt@amd.com 11068579Ssteve.reinhardt@amd.com# When initializing an IpWithPort, pass in an existing IpWithPort, a string of 11078579Ssteve.reinhardt@amd.com# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments. 11088579Ssteve.reinhardt@amd.comclass IpWithPort(IpAddress): 11098579Ssteve.reinhardt@amd.com cxx_type = 'Net::IpWithPort' 11108579Ssteve.reinhardt@amd.com ex_str = "127.0.0.1:80" 11118579Ssteve.reinhardt@amd.com cmd_line_settable = True 11128579Ssteve.reinhardt@amd.com 11137777Sgblack@eecs.umich.edu @classmethod 11147777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 11157777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 11167777Sgblack@eecs.umich.edu 11177777Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 11187777Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 111911988Sandreas.sandberg@arm.com if key in kwargs: 11207777Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 11217777Sgblack@eecs.umich.edu elif elseVal: 11223932Sbinkertn@umich.edu setattr(self, key, elseVal) 112310380SAndrew.Bardsley@arm.com else: 11243932Sbinkertn@umich.edu raise TypeError("No value set for %s" % key) 11253932Sbinkertn@umich.edu 11263932Sbinkertn@umich.edu if len(args) == 0: 11273932Sbinkertn@umich.edu handle_kwarg(self, kwargs, 'ip') 11283932Sbinkertn@umich.edu handle_kwarg(self, kwargs, 'port') 11293932Sbinkertn@umich.edu 11303932Sbinkertn@umich.edu elif len(args) == 1: 11313932Sbinkertn@umich.edu if kwargs: 11323932Sbinkertn@umich.edu if not 'ip' in kwargs and not 'port' in kwargs: 11333932Sbinkertn@umich.edu raise TypeError("Invalid arguments") 11343932Sbinkertn@umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 11353885Sbinkertn@umich.edu handle_kwarg(self, kwargs, 'port', args[0]) 11363932Sbinkertn@umich.edu elif isinstance(args[0], IpWithPort): 11373932Sbinkertn@umich.edu self.ip = args[0].ip 11383885Sbinkertn@umich.edu self.port = args[0].port 11393932Sbinkertn@umich.edu else: 11403932Sbinkertn@umich.edu (self.ip, self.port) = convert.toIpWithPort(args[0]) 11413932Sbinkertn@umich.edu 11423932Sbinkertn@umich.edu elif len(args) == 2: 11433932Sbinkertn@umich.edu self.ip = args[0] 11443932Sbinkertn@umich.edu self.port = args[1] 11453932Sbinkertn@umich.edu else: 11463932Sbinkertn@umich.edu raise TypeError("Too many arguments specified") 11473932Sbinkertn@umich.edu 11483932Sbinkertn@umich.edu if kwargs: 11493932Sbinkertn@umich.edu raise TypeError("Too many keywords: %s" % list(kwargs.keys())) 11503932Sbinkertn@umich.edu 11513932Sbinkertn@umich.edu self.verify() 11523932Sbinkertn@umich.edu 11533932Sbinkertn@umich.edu def __call__(self, value): 11543932Sbinkertn@umich.edu self.__init__(value) 11553932Sbinkertn@umich.edu return value 11563932Sbinkertn@umich.edu 11573885Sbinkertn@umich.edu def __str__(self): 11583885Sbinkertn@umich.edu return "%s:%d" % (super(IpWithPort, self).__str__(), self.port) 11593885Sbinkertn@umich.edu 11603885Sbinkertn@umich.edu def __eq__(self, other): 11614762Snate@binkert.org if isinstance(other, IpWithPort): 11627673Snate@binkert.org return self.ip == other.ip and self.port == other.port 11637673Snate@binkert.org elif isinstance(other, str): 11647673Snate@binkert.org try: 11657673Snate@binkert.org return (self.ip, self.port) == convert.toIpWithPort(other) 11667673Snate@binkert.org except: 11673885Sbinkertn@umich.edu return False 11683932Sbinkertn@umich.edu else: 11693885Sbinkertn@umich.edu return False 117010267SGeoffrey.Blake@arm.com 117110267SGeoffrey.Blake@arm.com def verify(self): 117210267SGeoffrey.Blake@arm.com self.verifyIp() 117310267SGeoffrey.Blake@arm.com if self.port < 0 or self.port > 0xffff: 11744762Snate@binkert.org raise TypeError("invalid port %d" % self.port) 117511988Sandreas.sandberg@arm.com 117611988Sandreas.sandberg@arm.com def getValue(self): 11774762Snate@binkert.org from _m5.net import IpWithPort 117811988Sandreas.sandberg@arm.com return IpWithPort(self.ip, self.port) 11794762Snate@binkert.org 11803885Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 11814762Snate@binkert.org "%a %b %d %H:%M:%S %Y", 11823885Sbinkertn@umich.edu "%Y/%m/%d %H:%M:%S", 11833885Sbinkertn@umich.edu "%Y/%m/%d %H:%M", 11843932Sbinkertn@umich.edu "%Y/%m/%d", 11853885Sbinkertn@umich.edu "%m/%d/%Y %H:%M:%S", 11868664SAli.Saidi@ARM.com "%m/%d/%Y %H:%M", 118710380SAndrew.Bardsley@arm.com "%m/%d/%Y", 11888664SAli.Saidi@ARM.com "%m/%d/%y %H:%M:%S", 11898664SAli.Saidi@ARM.com "%m/%d/%y %H:%M", 119010458Sandreas.hansson@arm.com "%m/%d/%y"] 119110458Sandreas.hansson@arm.com 119210458Sandreas.hansson@arm.com 119310458Sandreas.hansson@arm.comdef parse_time(value): 119410458Sandreas.hansson@arm.com from time import gmtime, strptime, struct_time, time 119510458Sandreas.hansson@arm.com from datetime import datetime, date 119610458Sandreas.hansson@arm.com 119710458Sandreas.hansson@arm.com if isinstance(value, struct_time): 119810458Sandreas.hansson@arm.com return value 119910458Sandreas.hansson@arm.com 12003101Sstever@eecs.umich.edu if isinstance(value, (int, long)): 12013101Sstever@eecs.umich.edu return gmtime(value) 12023101Sstever@eecs.umich.edu 12033101Sstever@eecs.umich.edu if isinstance(value, (datetime, date)): 12043101Sstever@eecs.umich.edu return value.timetuple() 12053101Sstever@eecs.umich.edu 12063101Sstever@eecs.umich.edu if isinstance(value, str): 12073101Sstever@eecs.umich.edu if value in ('Now', 'Today'): 12083101Sstever@eecs.umich.edu return time.gmtime(time.time()) 12093101Sstever@eecs.umich.edu 12103101Sstever@eecs.umich.edu for format in time_formats: 12113101Sstever@eecs.umich.edu try: 12123101Sstever@eecs.umich.edu return strptime(value, format) 12133101Sstever@eecs.umich.edu except ValueError: 12144762Snate@binkert.org pass 12153101Sstever@eecs.umich.edu 12165033Smilesck@eecs.umich.edu raise ValueError("Could not parse '%s' as a time" % value) 12174762Snate@binkert.org 12184762Snate@binkert.orgclass Time(ParamValue): 12194762Snate@binkert.org cxx_type = 'tm' 12204762Snate@binkert.org 12214762Snate@binkert.org @classmethod 12224762Snate@binkert.org def cxx_predecls(cls, code): 12234762Snate@binkert.org code('#include <time.h>') 12243101Sstever@eecs.umich.edu 12253101Sstever@eecs.umich.edu def __init__(self, value): 12263101Sstever@eecs.umich.edu self.value = parse_time(value) 12273101Sstever@eecs.umich.edu 12283101Sstever@eecs.umich.edu def __call__(self, value): 12293101Sstever@eecs.umich.edu self.__init__(value) 12303101Sstever@eecs.umich.edu return value 12313101Sstever@eecs.umich.edu 12323101Sstever@eecs.umich.edu def getValue(self): 12333101Sstever@eecs.umich.edu from _m5.core import tm 12343101Sstever@eecs.umich.edu import calendar 12353101Sstever@eecs.umich.edu 12363101Sstever@eecs.umich.edu return tm.gmtime(calendar.timegm(self.value)) 12373101Sstever@eecs.umich.edu 12383101Sstever@eecs.umich.edu def __str__(self): 12393101Sstever@eecs.umich.edu return time.asctime(self.value) 12403101Sstever@eecs.umich.edu 12413101Sstever@eecs.umich.edu def ini_str(self): 12423101Sstever@eecs.umich.edu return str(self) 12433101Sstever@eecs.umich.edu 12444762Snate@binkert.org def get_config_as_dict(self): 12453101Sstever@eecs.umich.edu assert false 12463101Sstever@eecs.umich.edu return str(self) 12473101Sstever@eecs.umich.edu 12483101Sstever@eecs.umich.edu @classmethod 12493101Sstever@eecs.umich.edu def cxx_ini_predecls(cls, code): 12503101Sstever@eecs.umich.edu code('#include <time.h>') 12517673Snate@binkert.org 125210201SAndrew.Bardsley@arm.com @classmethod 125310201SAndrew.Bardsley@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 125410201SAndrew.Bardsley@arm.com code('char *_parse_ret = strptime((${src}).c_str(),') 125510201SAndrew.Bardsley@arm.com code(' "%a %b %d %H:%M:%S %Y", &(${dest}));') 125610201SAndrew.Bardsley@arm.com code('${ret} _parse_ret && *_parse_ret == \'\\0\';'); 12577673Snate@binkert.org 125810201SAndrew.Bardsley@arm.com# Enumerated types are a little more complex. The user specifies the 125910201SAndrew.Bardsley@arm.com# type as Enum(foo) where foo is either a list or dictionary of 12607673Snate@binkert.org# alternatives (typically strings, but not necessarily so). (In the 126110201SAndrew.Bardsley@arm.com# long run, the integer value of the parameter will be the list index 12627673Snate@binkert.org# or the corresponding dictionary value. For now, since we only check 12637673Snate@binkert.org# that the alternative is valid and then spit it into a .ini file, 12647673Snate@binkert.org# there's not much point in using the dictionary.) 12654762Snate@binkert.org 12667673Snate@binkert.org# What Enum() must do is generate a new type encapsulating the 12678902Sandreas.hansson@arm.com# provided list/dictionary so that specific values of the parameter 12687673Snate@binkert.org# can be instances of that type. We define two hidden internal 126910201SAndrew.Bardsley@arm.com# classes (_ListEnum and _DictEnum) to serve as base classes, then 12704762Snate@binkert.org# derive the new type from the appropriate base class on the fly. 127110201SAndrew.Bardsley@arm.com 127210201SAndrew.Bardsley@arm.comallEnums = {} 127310201SAndrew.Bardsley@arm.com# Metaclass for Enum types 127410201SAndrew.Bardsley@arm.comclass MetaEnum(MetaParamValue): 127510201SAndrew.Bardsley@arm.com def __new__(mcls, name, bases, dict): 127610201SAndrew.Bardsley@arm.com assert name not in allEnums 127710201SAndrew.Bardsley@arm.com 127810201SAndrew.Bardsley@arm.com cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 127910201SAndrew.Bardsley@arm.com allEnums[name] = cls 12807673Snate@binkert.org return cls 12817673Snate@binkert.org 128210201SAndrew.Bardsley@arm.com def __init__(cls, name, bases, init_dict): 128310201SAndrew.Bardsley@arm.com if 'map' in init_dict: 128410201SAndrew.Bardsley@arm.com if not isinstance(cls.map, dict): 128510201SAndrew.Bardsley@arm.com raise TypeError("Enum-derived class attribute 'map' " \ 128610201SAndrew.Bardsley@arm.com "must be of type dict") 128710201SAndrew.Bardsley@arm.com # build list of value strings from map 128810201SAndrew.Bardsley@arm.com cls.vals = list(cls.map.keys()) 128910201SAndrew.Bardsley@arm.com cls.vals.sort() 129010201SAndrew.Bardsley@arm.com elif 'vals' in init_dict: 129110201SAndrew.Bardsley@arm.com if not isinstance(cls.vals, list): 129210201SAndrew.Bardsley@arm.com raise TypeError("Enum-derived class attribute 'vals' " \ 129310201SAndrew.Bardsley@arm.com "must be of type list") 129410201SAndrew.Bardsley@arm.com # build string->value map from vals sequence 129510201SAndrew.Bardsley@arm.com cls.map = {} 129610201SAndrew.Bardsley@arm.com for idx,val in enumerate(cls.vals): 12974762Snate@binkert.org cls.map[val] = idx 12987673Snate@binkert.org else: 129910201SAndrew.Bardsley@arm.com raise TypeError("Enum-derived class must define "\ 130010201SAndrew.Bardsley@arm.com "attribute 'map' or 'vals'") 130110201SAndrew.Bardsley@arm.com 130210201SAndrew.Bardsley@arm.com if cls.is_class: 130310201SAndrew.Bardsley@arm.com cls.cxx_type = '%s' % name 130410201SAndrew.Bardsley@arm.com else: 13053101Sstever@eecs.umich.edu cls.cxx_type = 'Enums::%s' % name 130611988Sandreas.sandberg@arm.com 130711988Sandreas.sandberg@arm.com super(MetaEnum, cls).__init__(name, bases, init_dict) 130811988Sandreas.sandberg@arm.com 130911988Sandreas.sandberg@arm.com # Generate C++ class declaration for this enum type. 131011988Sandreas.sandberg@arm.com # Note that we wrap the enum in a class/struct to act as a namespace, 131111988Sandreas.sandberg@arm.com # so that the enum strings can be brief w/o worrying about collisions. 131211988Sandreas.sandberg@arm.com def cxx_decl(cls, code): 131311988Sandreas.sandberg@arm.com wrapper_name = cls.wrapper_name 131411988Sandreas.sandberg@arm.com wrapper = 'struct' if cls.wrapper_is_struct else 'namespace' 131511988Sandreas.sandberg@arm.com name = cls.__name__ if cls.enum_name is None else cls.enum_name 131611988Sandreas.sandberg@arm.com idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name) 131711988Sandreas.sandberg@arm.com 131811988Sandreas.sandberg@arm.com code('''\ 131911988Sandreas.sandberg@arm.com#ifndef $idem_macro 132011988Sandreas.sandberg@arm.com#define $idem_macro 132111988Sandreas.sandberg@arm.com 132211988Sandreas.sandberg@arm.com''') 132311988Sandreas.sandberg@arm.com if cls.is_class: 132411988Sandreas.sandberg@arm.com code('''\ 132511988Sandreas.sandberg@arm.comenum class $name { 132611988Sandreas.sandberg@arm.com''') 132711988Sandreas.sandberg@arm.com else: 132811988Sandreas.sandberg@arm.com code('''\ 132911988Sandreas.sandberg@arm.com$wrapper $wrapper_name { 133011988Sandreas.sandberg@arm.com enum $name { 133111988Sandreas.sandberg@arm.com''') 133211988Sandreas.sandberg@arm.com code.indent(1) 133311988Sandreas.sandberg@arm.com code.indent(1) 133411988Sandreas.sandberg@arm.com for val in cls.vals: 133511988Sandreas.sandberg@arm.com code('$val = ${{cls.map[val]}},') 133611988Sandreas.sandberg@arm.com code('Num_$name = ${{len(cls.vals)}}') 133711988Sandreas.sandberg@arm.com code.dedent(1) 133811988Sandreas.sandberg@arm.com code('};') 133911988Sandreas.sandberg@arm.com 13408596Ssteve.reinhardt@amd.com if cls.is_class: 13413101Sstever@eecs.umich.edu code('''\ 13423101Sstever@eecs.umich.eduextern const char *${name}Strings[static_cast<int>(${name}::Num_${name})]; 13433101Sstever@eecs.umich.edu''') 13443101Sstever@eecs.umich.edu elif cls.wrapper_is_struct: 134510267SGeoffrey.Blake@arm.com code('static const char *${name}Strings[Num_${name}];') 13463101Sstever@eecs.umich.edu else: 134710201SAndrew.Bardsley@arm.com code('extern const char *${name}Strings[Num_${name}];') 134810201SAndrew.Bardsley@arm.com 134910201SAndrew.Bardsley@arm.com if not cls.is_class: 135010201SAndrew.Bardsley@arm.com code.dedent(1) 135110201SAndrew.Bardsley@arm.com code('};') 135210201SAndrew.Bardsley@arm.com 135310201SAndrew.Bardsley@arm.com code() 135410201SAndrew.Bardsley@arm.com code('#endif // $idem_macro') 135510201SAndrew.Bardsley@arm.com 13563101Sstever@eecs.umich.edu def cxx_def(cls, code): 13573101Sstever@eecs.umich.edu wrapper_name = cls.wrapper_name 13583101Sstever@eecs.umich.edu file_name = cls.__name__ 13593101Sstever@eecs.umich.edu name = cls.__name__ if cls.enum_name is None else cls.enum_name 13603101Sstever@eecs.umich.edu 13613101Sstever@eecs.umich.edu code('#include "enums/$file_name.hh"') 136210267SGeoffrey.Blake@arm.com if cls.wrapper_is_struct: 136310267SGeoffrey.Blake@arm.com code('const char *${wrapper_name}::${name}Strings' 136410267SGeoffrey.Blake@arm.com '[Num_${name}] =') 136510267SGeoffrey.Blake@arm.com else: 13667675Snate@binkert.org if cls.is_class: 13677675Snate@binkert.org code('''\ 13687675Snate@binkert.orgconst char *${name}Strings[static_cast<int>(${name}::Num_${name})] = 13697675Snate@binkert.org''') 13707675Snate@binkert.org else: 137110458Sandreas.hansson@arm.com code('namespace Enums {') 137210458Sandreas.hansson@arm.com code.indent(1) 137310458Sandreas.hansson@arm.com code('const char *${name}Strings[Num_${name}] =') 137410458Sandreas.hansson@arm.com 137510458Sandreas.hansson@arm.com code('{') 137610458Sandreas.hansson@arm.com code.indent(1) 137710458Sandreas.hansson@arm.com for val in cls.vals: 137810458Sandreas.hansson@arm.com code('"$val",') 137910458Sandreas.hansson@arm.com code.dedent(1) 138010458Sandreas.hansson@arm.com code('};') 138110458Sandreas.hansson@arm.com 138210458Sandreas.hansson@arm.com if not cls.wrapper_is_struct and not cls.is_class: 13834762Snate@binkert.org code.dedent(1) 138411988Sandreas.sandberg@arm.com code('} // namespace $wrapper_name') 138511988Sandreas.sandberg@arm.com 138611988Sandreas.sandberg@arm.com 13874762Snate@binkert.org def pybind_def(cls, code): 13883101Sstever@eecs.umich.edu name = cls.__name__ 13893101Sstever@eecs.umich.edu enum_name = cls.__name__ if cls.enum_name is None else cls.enum_name 13903101Sstever@eecs.umich.edu wrapper_name = enum_name if cls.is_class else cls.wrapper_name 13913101Sstever@eecs.umich.edu 13923101Sstever@eecs.umich.edu code('''#include "pybind11/pybind11.h" 13933101Sstever@eecs.umich.edu#include "pybind11/stl.h" 13944167Sbinkertn@umich.edu 13953101Sstever@eecs.umich.edu#include <sim/init.hh> 139610267SGeoffrey.Blake@arm.com 139710267SGeoffrey.Blake@arm.comnamespace py = pybind11; 13987673Snate@binkert.org 13997673Snate@binkert.orgstatic void 14007673Snate@binkert.orgmodule_init(py::module &m_internal) 14017673Snate@binkert.org{ 14027673Snate@binkert.org py::module m = m_internal.def_submodule("enum_${name}"); 140310267SGeoffrey.Blake@arm.com 140410267SGeoffrey.Blake@arm.com''') 140510267SGeoffrey.Blake@arm.com if cls.is_class: 140610267SGeoffrey.Blake@arm.com code('py::enum_<${enum_name}>(m, "enum_${name}")') 14074762Snate@binkert.org else: 14084762Snate@binkert.org code('py::enum_<${wrapper_name}::${enum_name}>(m, "enum_${name}")') 14094762Snate@binkert.org 141010458Sandreas.hansson@arm.com code.indent() 141110458Sandreas.hansson@arm.com code.indent() 141210458Sandreas.hansson@arm.com for val in cls.vals: 141310458Sandreas.hansson@arm.com code('.value("${val}", ${wrapper_name}::${val})') 141410458Sandreas.hansson@arm.com code('.value("Num_${name}", ${wrapper_name}::Num_${enum_name})') 141510458Sandreas.hansson@arm.com code('.export_values()') 141610458Sandreas.hansson@arm.com code(';') 141710458Sandreas.hansson@arm.com code.dedent() 141810458Sandreas.hansson@arm.com 141910458Sandreas.hansson@arm.com code('}') 14204167Sbinkertn@umich.edu code.dedent() 142110267SGeoffrey.Blake@arm.com code() 142210267SGeoffrey.Blake@arm.com code('static EmbeddedPyBind embed_enum("enum_${name}", module_init);') 14233101Sstever@eecs.umich.edu 14244167Sbinkertn@umich.edu 14254167Sbinkertn@umich.edu# Base class for enum types. 14264167Sbinkertn@umich.educlass Enum(ParamValue): 14274167Sbinkertn@umich.edu __metaclass__ = MetaEnum 14284167Sbinkertn@umich.edu vals = [] 14294167Sbinkertn@umich.edu cmd_line_settable = True 14304167Sbinkertn@umich.edu 14314167Sbinkertn@umich.edu # The name of the wrapping namespace or struct 14324167Sbinkertn@umich.edu wrapper_name = 'Enums' 14334167Sbinkertn@umich.edu 14344167Sbinkertn@umich.edu # If true, the enum is wrapped in a struct rather than a namespace 14354167Sbinkertn@umich.edu wrapper_is_struct = False 14363101Sstever@eecs.umich.edu 143710267SGeoffrey.Blake@arm.com is_class = False 143810267SGeoffrey.Blake@arm.com 143910267SGeoffrey.Blake@arm.com # If not None, use this as the enum name rather than this class name 144010267SGeoffrey.Blake@arm.com enum_name = None 14413101Sstever@eecs.umich.edu 14423101Sstever@eecs.umich.edu def __init__(self, value): 14433101Sstever@eecs.umich.edu if value not in self.map: 14443101Sstever@eecs.umich.edu raise TypeError("Enum param got bad value '%s' (not in %s)" \ 14453101Sstever@eecs.umich.edu % (value, self.vals)) 14463101Sstever@eecs.umich.edu self.value = value 14473101Sstever@eecs.umich.edu 14484762Snate@binkert.org def __call__(self, value): 14494762Snate@binkert.org self.__init__(value) 14504762Snate@binkert.org return value 14514762Snate@binkert.org 14524762Snate@binkert.org @classmethod 14534762Snate@binkert.org def cxx_predecls(cls, code): 14544762Snate@binkert.org code('#include "enums/$0.hh"', cls.__name__) 145510380SAndrew.Bardsley@arm.com 145610380SAndrew.Bardsley@arm.com @classmethod 145710380SAndrew.Bardsley@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 14583101Sstever@eecs.umich.edu code('if (false) {') 14593101Sstever@eecs.umich.edu for elem_name in cls.map.keys(): 14604762Snate@binkert.org code('} else if (%s == "%s") {' % (src, elem_name)) 14613101Sstever@eecs.umich.edu code.indent() 14624167Sbinkertn@umich.edu code('%s = Enums::%s;' % (dest, elem_name)) 146310267SGeoffrey.Blake@arm.com code('%s true;' % ret) 146410267SGeoffrey.Blake@arm.com code.dedent() 14653101Sstever@eecs.umich.edu code('} else {') 14664167Sbinkertn@umich.edu code(' %s false;' % ret) 14674167Sbinkertn@umich.edu code('}') 14684167Sbinkertn@umich.edu 14694167Sbinkertn@umich.edu def getValue(self): 14704167Sbinkertn@umich.edu import m5.internal.params 14714167Sbinkertn@umich.edu e = getattr(m5.internal.params, "enum_%s" % self.__class__.__name__) 14724167Sbinkertn@umich.edu return e(self.map[self.value]) 14734167Sbinkertn@umich.edu 14744167Sbinkertn@umich.edu def __str__(self): 14754167Sbinkertn@umich.edu return self.value 14764167Sbinkertn@umich.edu 14774167Sbinkertn@umich.edu# This param will generate a scoped c++ enum and its python bindings. 14783101Sstever@eecs.umich.educlass ScopedEnum(Enum): 147910267SGeoffrey.Blake@arm.com __metaclass__ = MetaEnum 148010267SGeoffrey.Blake@arm.com vals = [] 148110267SGeoffrey.Blake@arm.com cmd_line_settable = True 148210267SGeoffrey.Blake@arm.com 14833101Sstever@eecs.umich.edu # The name of the wrapping namespace or struct 14843101Sstever@eecs.umich.edu wrapper_name = None 14853101Sstever@eecs.umich.edu 14863101Sstever@eecs.umich.edu # If true, the enum is wrapped in a struct rather than a namespace 14873101Sstever@eecs.umich.edu wrapper_is_struct = False 14883101Sstever@eecs.umich.edu 14893101Sstever@eecs.umich.edu # If true, the generated enum is a scoped enum 14904167Sbinkertn@umich.edu is_class = True 14914762Snate@binkert.org 14924762Snate@binkert.org # If not None, use this as the enum name rather than this class name 14934762Snate@binkert.org enum_name = None 14944762Snate@binkert.org 14954762Snate@binkert.org# how big does a rounding error need to be before we warn about it? 14964762Snate@binkert.orgfrequency_tolerance = 0.001 # 0.1% 14974762Snate@binkert.org 149810380SAndrew.Bardsley@arm.comclass TickParamValue(NumericParamValue): 149910380SAndrew.Bardsley@arm.com cxx_type = 'Tick' 150010380SAndrew.Bardsley@arm.com ex_str = "1MHz" 15013101Sstever@eecs.umich.edu cmd_line_settable = True 15024762Snate@binkert.org 15033101Sstever@eecs.umich.edu @classmethod 150410019Sandreas.hansson@arm.com def cxx_predecls(cls, code): 150510019Sandreas.hansson@arm.com code('#include "base/types.hh"') 150610019Sandreas.hansson@arm.com 15073101Sstever@eecs.umich.edu def __call__(self, value): 15084167Sbinkertn@umich.edu self.__init__(value) 15094167Sbinkertn@umich.edu return value 15104167Sbinkertn@umich.edu 15114167Sbinkertn@umich.edu def getValue(self): 15124167Sbinkertn@umich.edu return long(self.value) 15134167Sbinkertn@umich.edu 15144167Sbinkertn@umich.edu @classmethod 15154167Sbinkertn@umich.edu def cxx_ini_predecls(cls, code): 15164167Sbinkertn@umich.edu code('#include <sstream>') 15174167Sbinkertn@umich.edu 15184167Sbinkertn@umich.edu # Ticks are expressed in seconds in JSON files and in plain 15194167Sbinkertn@umich.edu # Ticks in .ini files. Switch based on a config flag 15203101Sstever@eecs.umich.edu @classmethod 152110267SGeoffrey.Blake@arm.com def cxx_ini_parse(self, code, src, dest, ret): 152210267SGeoffrey.Blake@arm.com code('${ret} to_number(${src}, ${dest});') 152310267SGeoffrey.Blake@arm.com 152410267SGeoffrey.Blake@arm.comclass Latency(TickParamValue): 152510267SGeoffrey.Blake@arm.com ex_str = "100ns" 152610267SGeoffrey.Blake@arm.com 152710267SGeoffrey.Blake@arm.com def __init__(self, value): 15283101Sstever@eecs.umich.edu if isinstance(value, (Latency, Clock)): 15293101Sstever@eecs.umich.edu self.ticks = value.ticks 15303101Sstever@eecs.umich.edu self.value = value.value 15313101Sstever@eecs.umich.edu elif isinstance(value, Frequency): 15323101Sstever@eecs.umich.edu self.ticks = value.ticks 15333101Sstever@eecs.umich.edu self.value = 1.0 / value.value 15343101Sstever@eecs.umich.edu elif value.endswith('t'): 15354762Snate@binkert.org self.ticks = True 15364762Snate@binkert.org self.value = int(value[:-1]) 15374762Snate@binkert.org else: 153810380SAndrew.Bardsley@arm.com self.ticks = False 153910380SAndrew.Bardsley@arm.com self.value = convert.toLatency(value) 154010380SAndrew.Bardsley@arm.com 15413101Sstever@eecs.umich.edu def __call__(self, value): 15423101Sstever@eecs.umich.edu self.__init__(value) 15433101Sstever@eecs.umich.edu return value 15449827Sakash.bagdia@arm.com 15459827Sakash.bagdia@arm.com def __getattr__(self, attr): 154610267SGeoffrey.Blake@arm.com if attr in ('latency', 'period'): 154711498Sakash.bagdia@ARM.com return self 154810267SGeoffrey.Blake@arm.com if attr == 'frequency': 15499827Sakash.bagdia@arm.com return Frequency(self) 15509827Sakash.bagdia@arm.com raise AttributeError("Latency object has no attribute '%s'" % attr) 15519827Sakash.bagdia@arm.com 15529827Sakash.bagdia@arm.com def getValue(self): 15539827Sakash.bagdia@arm.com if self.ticks or self.value == 0: 155410267SGeoffrey.Blake@arm.com value = self.value 155510267SGeoffrey.Blake@arm.com else: 155610267SGeoffrey.Blake@arm.com value = ticks.fromSeconds(self.value) 155710267SGeoffrey.Blake@arm.com return long(value) 155810267SGeoffrey.Blake@arm.com 15599827Sakash.bagdia@arm.com def config_value(self): 156010267SGeoffrey.Blake@arm.com return self.getValue() 15619827Sakash.bagdia@arm.com 15629827Sakash.bagdia@arm.com # convert latency to ticks 15639827Sakash.bagdia@arm.com def ini_str(self): 15649827Sakash.bagdia@arm.com return '%d' % self.getValue() 15659827Sakash.bagdia@arm.com 15669827Sakash.bagdia@arm.comclass Frequency(TickParamValue): 15679827Sakash.bagdia@arm.com ex_str = "1GHz" 15689827Sakash.bagdia@arm.com 156910458Sandreas.hansson@arm.com def __init__(self, value): 157010458Sandreas.hansson@arm.com if isinstance(value, (Latency, Clock)): 157110458Sandreas.hansson@arm.com if value.value == 0: 157210458Sandreas.hansson@arm.com self.value = 0 157310458Sandreas.hansson@arm.com else: 157410458Sandreas.hansson@arm.com self.value = 1.0 / value.value 157510458Sandreas.hansson@arm.com self.ticks = value.ticks 157610458Sandreas.hansson@arm.com elif isinstance(value, Frequency): 157710427Sandreas.hansson@arm.com self.value = value.value 157810427Sandreas.hansson@arm.com self.ticks = value.ticks 157910427Sandreas.hansson@arm.com else: 158010427Sandreas.hansson@arm.com self.ticks = False 158110427Sandreas.hansson@arm.com self.value = convert.toFrequency(value) 158210427Sandreas.hansson@arm.com 158310427Sandreas.hansson@arm.com def __call__(self, value): 158410427Sandreas.hansson@arm.com self.__init__(value) 158510427Sandreas.hansson@arm.com return value 158610427Sandreas.hansson@arm.com 158710427Sandreas.hansson@arm.com def __getattr__(self, attr): 158810427Sandreas.hansson@arm.com if attr == 'frequency': 158910427Sandreas.hansson@arm.com return self 159010427Sandreas.hansson@arm.com if attr in ('latency', 'period'): 159110427Sandreas.hansson@arm.com return Latency(self) 159210427Sandreas.hansson@arm.com raise AttributeError("Frequency object has no attribute '%s'" % attr) 159310427Sandreas.hansson@arm.com 159410427Sandreas.hansson@arm.com # convert latency to ticks 159510427Sandreas.hansson@arm.com def getValue(self): 159610427Sandreas.hansson@arm.com if self.ticks or self.value == 0: 159710427Sandreas.hansson@arm.com value = self.value 159810427Sandreas.hansson@arm.com else: 159910427Sandreas.hansson@arm.com value = ticks.fromSeconds(1.0 / self.value) 160010427Sandreas.hansson@arm.com return long(value) 160110427Sandreas.hansson@arm.com 160210458Sandreas.hansson@arm.com def config_value(self): 160310458Sandreas.hansson@arm.com return self.getValue() 160410458Sandreas.hansson@arm.com 160510458Sandreas.hansson@arm.com def ini_str(self): 160610458Sandreas.hansson@arm.com return '%d' % self.getValue() 160710458Sandreas.hansson@arm.com 160810458Sandreas.hansson@arm.com# A generic Frequency and/or Latency value. Value is stored as a 160910458Sandreas.hansson@arm.com# latency, just like Latency and Frequency. 16103101Sstever@eecs.umich.educlass Clock(TickParamValue): 16113101Sstever@eecs.umich.edu def __init__(self, value): 161210267SGeoffrey.Blake@arm.com if isinstance(value, (Latency, Clock)): 161310267SGeoffrey.Blake@arm.com self.ticks = value.ticks 161410267SGeoffrey.Blake@arm.com self.value = value.value 16153101Sstever@eecs.umich.edu elif isinstance(value, Frequency): 16164167Sbinkertn@umich.edu self.ticks = value.ticks 16174167Sbinkertn@umich.edu self.value = 1.0 / value.value 16183101Sstever@eecs.umich.edu elif value.endswith('t'): 16193101Sstever@eecs.umich.edu self.ticks = True 16203101Sstever@eecs.umich.edu self.value = int(value[:-1]) 16213101Sstever@eecs.umich.edu else: 16223101Sstever@eecs.umich.edu self.ticks = False 162310267SGeoffrey.Blake@arm.com self.value = convert.anyToLatency(value) 162410267SGeoffrey.Blake@arm.com 162510267SGeoffrey.Blake@arm.com def __call__(self, value): 162610267SGeoffrey.Blake@arm.com self.__init__(value) 162710267SGeoffrey.Blake@arm.com return value 16284762Snate@binkert.org 16294167Sbinkertn@umich.edu def __str__(self): 16304167Sbinkertn@umich.edu return "%s" % Latency(self) 16314167Sbinkertn@umich.edu 16324762Snate@binkert.org def __getattr__(self, attr): 16334762Snate@binkert.org if attr == 'frequency': 16344762Snate@binkert.org return Frequency(self) 16354762Snate@binkert.org if attr in ('latency', 'period'): 16364762Snate@binkert.org return Latency(self) 16373101Sstever@eecs.umich.edu raise AttributeError("Frequency object has no attribute '%s'" % attr) 163810380SAndrew.Bardsley@arm.com 163910380SAndrew.Bardsley@arm.com def getValue(self): 164010380SAndrew.Bardsley@arm.com return self.period.getValue() 164110458Sandreas.hansson@arm.com 164210458Sandreas.hansson@arm.com def config_value(self): 164310458Sandreas.hansson@arm.com return self.period.config_value() 164410458Sandreas.hansson@arm.com 164510458Sandreas.hansson@arm.com def ini_str(self): 164610458Sandreas.hansson@arm.com return self.period.ini_str() 164710458Sandreas.hansson@arm.com 164810458Sandreas.hansson@arm.comclass Voltage(Float): 16493101Sstever@eecs.umich.edu ex_str = "1V" 16503101Sstever@eecs.umich.edu 165110267SGeoffrey.Blake@arm.com def __new__(cls, value): 165210267SGeoffrey.Blake@arm.com value = convert.toVoltage(value) 165310267SGeoffrey.Blake@arm.com return super(cls, Voltage).__new__(cls, value) 16545469Snate@binkert.org 16557743Sgblack@eecs.umich.edu def __init__(self, value): 16563102Sstever@eecs.umich.edu value = convert.toVoltage(value) 16573101Sstever@eecs.umich.edu super(Voltage, self).__init__(value) 16583101Sstever@eecs.umich.edu 165910267SGeoffrey.Blake@arm.comclass Current(Float): 166010267SGeoffrey.Blake@arm.com ex_str = "1mA" 166110267SGeoffrey.Blake@arm.com 166210267SGeoffrey.Blake@arm.com def __new__(cls, value): 16633101Sstever@eecs.umich.edu value = convert.toCurrent(value) 16644762Snate@binkert.org return super(cls, Current).__new__(cls, value) 16654167Sbinkertn@umich.edu 16665468Snate@binkert.org def __init__(self, value): 16675468Snate@binkert.org value = convert.toCurrent(value) 16685468Snate@binkert.org super(Current, self).__init__(value) 16694167Sbinkertn@umich.edu 16704762Snate@binkert.orgclass Energy(Float): 16714762Snate@binkert.org ex_str = "1pJ" 16724762Snate@binkert.org 16734762Snate@binkert.org def __new__(cls, value): 16744762Snate@binkert.org value = convert.toEnergy(value) 16753101Sstever@eecs.umich.edu return super(cls, Energy).__new__(cls, value) 167610380SAndrew.Bardsley@arm.com 167710380SAndrew.Bardsley@arm.com def __init__(self, value): 167810380SAndrew.Bardsley@arm.com value = convert.toEnergy(value) 167910458Sandreas.hansson@arm.com super(Energy, self).__init__(value) 168010458Sandreas.hansson@arm.com 168110458Sandreas.hansson@arm.comclass NetworkBandwidth(float,ParamValue): 168210458Sandreas.hansson@arm.com cxx_type = 'float' 168310458Sandreas.hansson@arm.com ex_str = "1Gbps" 168410458Sandreas.hansson@arm.com cmd_line_settable = True 168510458Sandreas.hansson@arm.com 168610458Sandreas.hansson@arm.com def __new__(cls, value): 16873101Sstever@eecs.umich.edu # convert to bits per second 16883101Sstever@eecs.umich.edu val = convert.toNetworkBandwidth(value) 16893101Sstever@eecs.umich.edu return super(cls, NetworkBandwidth).__new__(cls, val) 16903101Sstever@eecs.umich.edu 16913102Sstever@eecs.umich.edu def __str__(self): 16923102Sstever@eecs.umich.edu return str(self.val) 16933102Sstever@eecs.umich.edu 16943102Sstever@eecs.umich.edu def __call__(self, value): 16953102Sstever@eecs.umich.edu val = convert.toNetworkBandwidth(value) 16963102Sstever@eecs.umich.edu self.__init__(val) 169712197Sgabeblack@google.com return value 16983102Sstever@eecs.umich.edu 16993102Sstever@eecs.umich.edu def getValue(self): 17003102Sstever@eecs.umich.edu # convert to seconds per byte 17013102Sstever@eecs.umich.edu value = 8.0 / float(self) 17023102Sstever@eecs.umich.edu # convert to ticks per byte 17033102Sstever@eecs.umich.edu value = ticks.fromSeconds(value) 17043102Sstever@eecs.umich.edu return float(value) 17053102Sstever@eecs.umich.edu 17063102Sstever@eecs.umich.edu def ini_str(self): 17073102Sstever@eecs.umich.edu return '%f' % self.getValue() 17083102Sstever@eecs.umich.edu 17093102Sstever@eecs.umich.edu def config_value(self): 17103102Sstever@eecs.umich.edu return '%f' % self.getValue() 17113102Sstever@eecs.umich.edu 17123102Sstever@eecs.umich.edu @classmethod 17134762Snate@binkert.org def cxx_ini_predecls(cls, code): 171412192Sgabeblack@google.com code('#include <sstream>') 171512192Sgabeblack@google.com 171612192Sgabeblack@google.com @classmethod 171712195Sgabeblack@google.com def cxx_ini_parse(self, code, src, dest, ret): 171812195Sgabeblack@google.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 171912195Sgabeblack@google.com 172012196Sgabeblack@google.comclass MemoryBandwidth(float,ParamValue): 172112196Sgabeblack@google.com cxx_type = 'float' 172212196Sgabeblack@google.com ex_str = "1GB/s" 172312196Sgabeblack@google.com cmd_line_settable = True 172412200Sgabeblack@google.com 172512200Sgabeblack@google.com def __new__(cls, value): 172612200Sgabeblack@google.com # convert to bytes per second 17273102Sstever@eecs.umich.edu val = convert.toMemoryBandwidth(value) 172812197Sgabeblack@google.com return super(cls, MemoryBandwidth).__new__(cls, val) 17293102Sstever@eecs.umich.edu 173010380SAndrew.Bardsley@arm.com def __call__(self, value): 173110380SAndrew.Bardsley@arm.com val = convert.toMemoryBandwidth(value) 173210380SAndrew.Bardsley@arm.com self.__init__(val) 17334762Snate@binkert.org return value 17344762Snate@binkert.org 17354762Snate@binkert.org def getValue(self): 17363102Sstever@eecs.umich.edu # convert to seconds per byte 17373102Sstever@eecs.umich.edu value = float(self) 17383102Sstever@eecs.umich.edu if value: 17393102Sstever@eecs.umich.edu value = 1.0 / float(self) 17403102Sstever@eecs.umich.edu # convert to ticks per byte 17413102Sstever@eecs.umich.edu value = ticks.fromSeconds(value) 17423101Sstever@eecs.umich.edu return float(value) 17433101Sstever@eecs.umich.edu 17443101Sstever@eecs.umich.edu def ini_str(self): 17453101Sstever@eecs.umich.edu return '%f' % self.getValue() 17463101Sstever@eecs.umich.edu 17473101Sstever@eecs.umich.edu def config_value(self): 17483101Sstever@eecs.umich.edu return '%f' % self.getValue() 17493101Sstever@eecs.umich.edu 17503101Sstever@eecs.umich.edu @classmethod 17513101Sstever@eecs.umich.edu def cxx_ini_predecls(cls, code): 17523101Sstever@eecs.umich.edu code('#include <sstream>') 17533101Sstever@eecs.umich.edu 17543101Sstever@eecs.umich.edu @classmethod 17553101Sstever@eecs.umich.edu def cxx_ini_parse(self, code, src, dest, ret): 17563101Sstever@eecs.umich.edu code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 17573101Sstever@eecs.umich.edu 17583101Sstever@eecs.umich.edu# 17598839Sandreas.hansson@arm.com# "Constants"... handy aliases for various values. 17603105Sstever@eecs.umich.edu# 17613101Sstever@eecs.umich.edu 17623101Sstever@eecs.umich.edu# Special class for NULL pointers. Note the special check in 17638839Sandreas.hansson@arm.com# make_param_value() above that lets these be assigned where a 17643101Sstever@eecs.umich.edu# SimObject is required. 17653101Sstever@eecs.umich.edu# only one copy of a particular node 17663105Sstever@eecs.umich.educlass NullSimObject(object): 17673101Sstever@eecs.umich.edu __metaclass__ = Singleton 17683103Sstever@eecs.umich.edu _name = 'Null' 17693105Sstever@eecs.umich.edu 17703103Sstever@eecs.umich.edu def __call__(cls): 17718840Sandreas.hansson@arm.com return cls 17728840Sandreas.hansson@arm.com 17738840Sandreas.hansson@arm.com def _instantiate(self, parent = None, path = ''): 17748840Sandreas.hansson@arm.com pass 17758840Sandreas.hansson@arm.com 17763105Sstever@eecs.umich.edu def ini_str(self): 17773105Sstever@eecs.umich.edu return 'Null' 17783105Sstever@eecs.umich.edu 17793105Sstever@eecs.umich.edu def unproxy(self, base): 17809017Sandreas.hansson@arm.com return self 17819017Sandreas.hansson@arm.com 17829017Sandreas.hansson@arm.com def set_path(self, parent, name): 17839017Sandreas.hansson@arm.com pass 17843105Sstever@eecs.umich.edu 17853105Sstever@eecs.umich.edu def set_parent(self, parent, name): 17863105Sstever@eecs.umich.edu pass 17873105Sstever@eecs.umich.edu 17883105Sstever@eecs.umich.edu def clear_parent(self, old_parent): 17893105Sstever@eecs.umich.edu pass 17903105Sstever@eecs.umich.edu 17913105Sstever@eecs.umich.edu def descendants(self): 17923105Sstever@eecs.umich.edu return 17933109Sstever@eecs.umich.edu yield None 17943105Sstever@eecs.umich.edu 17953105Sstever@eecs.umich.edu def get_config_as_dict(self): 17963105Sstever@eecs.umich.edu return {} 17973105Sstever@eecs.umich.edu 17983105Sstever@eecs.umich.edu def __str__(self): 17993105Sstever@eecs.umich.edu return self._name 18009014Sandreas.hansson@arm.com 18019014Sandreas.hansson@arm.com def config_value(self): 18023101Sstever@eecs.umich.edu return None 18033109Sstever@eecs.umich.edu 18043109Sstever@eecs.umich.edu def getValue(self): 18053109Sstever@eecs.umich.edu return None 18063109Sstever@eecs.umich.edu 18073109Sstever@eecs.umich.edu# The only instance you'll ever need... 18083109Sstever@eecs.umich.eduNULL = NullSimObject() 18093109Sstever@eecs.umich.edu 18103109Sstever@eecs.umich.edudef isNullPointer(value): 18113109Sstever@eecs.umich.edu return isinstance(value, NullSimObject) 18123101Sstever@eecs.umich.edu 181310355SGeoffrey.Blake@arm.com# Some memory range specifications use this as a default upper bound. 181410355SGeoffrey.Blake@arm.comMaxAddr = Addr.max 181510355SGeoffrey.Blake@arm.comMaxTick = Tick.max 181610355SGeoffrey.Blake@arm.comAllMemory = AddrRange(0, MaxAddr) 181710355SGeoffrey.Blake@arm.com 181810355SGeoffrey.Blake@arm.com 181910355SGeoffrey.Blake@arm.com##################################################################### 182010355SGeoffrey.Blake@arm.com# 182110355SGeoffrey.Blake@arm.com# Port objects 182210355SGeoffrey.Blake@arm.com# 182310355SGeoffrey.Blake@arm.com# Ports are used to interconnect objects in the memory system. 182410355SGeoffrey.Blake@arm.com# 182510355SGeoffrey.Blake@arm.com##################################################################### 182610355SGeoffrey.Blake@arm.com 182710355SGeoffrey.Blake@arm.com# Port reference: encapsulates a reference to a particular port on a 182810355SGeoffrey.Blake@arm.com# particular SimObject. 182910355SGeoffrey.Blake@arm.comclass PortRef(object): 183010355SGeoffrey.Blake@arm.com def __init__(self, simobj, name, role): 183110355SGeoffrey.Blake@arm.com assert(isSimObject(simobj) or isSimObjectClass(simobj)) 183210355SGeoffrey.Blake@arm.com self.simobj = simobj 183310355SGeoffrey.Blake@arm.com self.name = name 183410355SGeoffrey.Blake@arm.com self.role = role 183510355SGeoffrey.Blake@arm.com self.peer = None # not associated with another port yet 183610355SGeoffrey.Blake@arm.com self.ccConnected = False # C++ port connection done? 183710355SGeoffrey.Blake@arm.com self.index = -1 # always -1 for non-vector ports 183810355SGeoffrey.Blake@arm.com 183910355SGeoffrey.Blake@arm.com def __str__(self): 184010355SGeoffrey.Blake@arm.com return '%s.%s' % (self.simobj, self.name) 184110355SGeoffrey.Blake@arm.com 184210355SGeoffrey.Blake@arm.com def __len__(self): 18433105Sstever@eecs.umich.edu # Return the number of connected ports, i.e. 0 is we have no 18443105Sstever@eecs.umich.edu # peer and 1 if we do. 18453105Sstever@eecs.umich.edu return int(self.peer != None) 18463101Sstever@eecs.umich.edu 18473105Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 18483105Sstever@eecs.umich.edu def ini_str(self): 18493101Sstever@eecs.umich.edu return str(self.peer) 18503105Sstever@eecs.umich.edu 18513179Sstever@eecs.umich.edu # for config.json 18523105Sstever@eecs.umich.edu def get_config_as_dict(self): 18533105Sstever@eecs.umich.edu return {'role' : self.role, 'peer' : str(self.peer)} 18543101Sstever@eecs.umich.edu 18553101Sstever@eecs.umich.edu def __getattr__(self, attr): 18563105Sstever@eecs.umich.edu if attr == 'peerObj': 18573105Sstever@eecs.umich.edu # shorthand for proxies 18583105Sstever@eecs.umich.edu return self.peer.simobj 18593105Sstever@eecs.umich.edu raise AttributeError("'%s' object has no attribute '%s'" % \ 18603105Sstever@eecs.umich.edu (self.__class__.__name__, attr)) 18613105Sstever@eecs.umich.edu 18623105Sstever@eecs.umich.edu # Full connection is symmetric (both ways). Called via 18633105Sstever@eecs.umich.edu # SimObject.__setattr__ as a result of a port assignment, e.g., 18643105Sstever@eecs.umich.edu # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 18653105Sstever@eecs.umich.edu # e.g., "obj1.portA[3] = obj2.portB". 18663105Sstever@eecs.umich.edu def connect(self, other): 18673101Sstever@eecs.umich.edu if isinstance(other, VectorPortRef): 18683101Sstever@eecs.umich.edu # reference to plain VectorPort is implicit append 186911802Sandreas.sandberg@arm.com other = other._get_next() 18704762Snate@binkert.org if self.peer and not proxy.isproxy(self.peer): 18718839Sandreas.hansson@arm.com fatal("Port %s is already connected to %s, cannot connect %s\n", 18728839Sandreas.hansson@arm.com self, self.peer, other); 18738839Sandreas.hansson@arm.com self.peer = other 18748839Sandreas.hansson@arm.com if proxy.isproxy(other): 18753101Sstever@eecs.umich.edu other.set_param_desc(PortParamDesc()) 18763101Sstever@eecs.umich.edu elif isinstance(other, PortRef): 18773101Sstever@eecs.umich.edu if other.peer is not self: 18785578SSteve.Reinhardt@amd.com other.connect(self) 18795578SSteve.Reinhardt@amd.com else: 18808839Sandreas.hansson@arm.com raise TypeError("assigning non-port reference '%s' to port '%s'" \ 18818839Sandreas.hansson@arm.com % (other, self)) 18828839Sandreas.hansson@arm.com 18838839Sandreas.hansson@arm.com # Allow a master/slave port pair to be spliced between 18848839Sandreas.hansson@arm.com # a port and its connected peer. Useful operation for connecting 18858839Sandreas.hansson@arm.com # instrumentation structures into a system when it is necessary 18868839Sandreas.hansson@arm.com # to connect the instrumentation after the full system has been 18877526Ssteve.reinhardt@amd.com # constructed. 18888839Sandreas.hansson@arm.com def splice(self, new_master_peer, new_slave_peer): 18897526Ssteve.reinhardt@amd.com if not self.peer or proxy.isproxy(self.peer): 18907526Ssteve.reinhardt@amd.com fatal("Port %s not connected, cannot splice in new peers\n", self) 18917526Ssteve.reinhardt@amd.com 18927526Ssteve.reinhardt@amd.com if not isinstance(new_master_peer, PortRef) or \ 18937526Ssteve.reinhardt@amd.com not isinstance(new_slave_peer, PortRef): 18947526Ssteve.reinhardt@amd.com raise TypeError( 18957526Ssteve.reinhardt@amd.com "Splicing non-port references '%s','%s' to port '%s'" % \ 18963101Sstever@eecs.umich.edu (new_master_peer, new_slave_peer, self)) 18973101Sstever@eecs.umich.edu 18983101Sstever@eecs.umich.edu old_peer = self.peer 18993105Sstever@eecs.umich.edu if self.role == 'SLAVE': 19003105Sstever@eecs.umich.edu self.peer = new_master_peer 19013105Sstever@eecs.umich.edu old_peer.peer = new_slave_peer 19028839Sandreas.hansson@arm.com new_master_peer.connect(self) 19038839Sandreas.hansson@arm.com new_slave_peer.connect(old_peer) 19043105Sstever@eecs.umich.edu elif self.role == 'MASTER': 19053105Sstever@eecs.umich.edu self.peer = new_slave_peer 19063105Sstever@eecs.umich.edu old_peer.peer = new_master_peer 19073105Sstever@eecs.umich.edu new_slave_peer.connect(self) 19083105Sstever@eecs.umich.edu new_master_peer.connect(old_peer) 19093105Sstever@eecs.umich.edu else: 19103105Sstever@eecs.umich.edu panic("Port %s has unknown role, "+\ 19113105Sstever@eecs.umich.edu "cannot splice in new peers\n", self) 19128839Sandreas.hansson@arm.com 19133105Sstever@eecs.umich.edu def clone(self, simobj, memo): 19143105Sstever@eecs.umich.edu if self in memo: 19153105Sstever@eecs.umich.edu return memo[self] 19168839Sandreas.hansson@arm.com newRef = copy.copy(self) 19173105Sstever@eecs.umich.edu memo[self] = newRef 19183105Sstever@eecs.umich.edu newRef.simobj = simobj 19193109Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 19203109Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 19213109Sstever@eecs.umich.edu peerObj = self.peer.simobj(_memo=memo) 19228840Sandreas.hansson@arm.com newRef.peer = self.peer.clone(peerObj, memo) 19238840Sandreas.hansson@arm.com assert(not isinstance(newRef.peer, VectorPortRef)) 19248840Sandreas.hansson@arm.com return newRef 19258840Sandreas.hansson@arm.com 19268840Sandreas.hansson@arm.com def unproxy(self, simobj): 19273105Sstever@eecs.umich.edu assert(simobj is self.simobj) 19283105Sstever@eecs.umich.edu if proxy.isproxy(self.peer): 19293105Sstever@eecs.umich.edu try: 19303105Sstever@eecs.umich.edu realPeer = self.peer.unproxy(self.simobj) 19319017Sandreas.hansson@arm.com except: 19329017Sandreas.hansson@arm.com print("Error in unproxying port '%s' of %s" % 19339017Sandreas.hansson@arm.com (self.name, self.simobj.path())) 19349017Sandreas.hansson@arm.com raise 19359017Sandreas.hansson@arm.com self.connect(realPeer) 19363105Sstever@eecs.umich.edu 19373105Sstever@eecs.umich.edu # Call C++ to create corresponding port connection between C++ objects 19383105Sstever@eecs.umich.edu def ccConnect(self): 19393105Sstever@eecs.umich.edu from _m5.pyobject import connectPorts 19403105Sstever@eecs.umich.edu 19418839Sandreas.hansson@arm.com if self.ccConnected: # already done this 19423105Sstever@eecs.umich.edu return 19433105Sstever@eecs.umich.edu 19443105Sstever@eecs.umich.edu peer = self.peer 19453105Sstever@eecs.umich.edu if not self.peer: # nothing to connect to 19463105Sstever@eecs.umich.edu return 19473105Sstever@eecs.umich.edu 19483105Sstever@eecs.umich.edu # check that we connect a master to a slave 19493105Sstever@eecs.umich.edu if self.role == peer.role: 19503105Sstever@eecs.umich.edu raise TypeError( 19513105Sstever@eecs.umich.edu "cannot connect '%s' and '%s' due to identical role '%s'" % \ 19523105Sstever@eecs.umich.edu (peer, self, self.role)) 19533105Sstever@eecs.umich.edu 19543105Sstever@eecs.umich.edu if self.role == 'SLAVE': 19553109Sstever@eecs.umich.edu # do nothing and let the master take care of it 19563109Sstever@eecs.umich.edu return 19573109Sstever@eecs.umich.edu 19583109Sstever@eecs.umich.edu try: 19593109Sstever@eecs.umich.edu # self is always the master and peer the slave 19603109Sstever@eecs.umich.edu connectPorts(self.simobj.getCCObject(), self.name, self.index, 19613109Sstever@eecs.umich.edu peer.simobj.getCCObject(), peer.name, peer.index) 19623109Sstever@eecs.umich.edu except: 19633109Sstever@eecs.umich.edu print("Error connecting port %s.%s to %s.%s" % 19643109Sstever@eecs.umich.edu (self.simobj.path(), self.name, 19653109Sstever@eecs.umich.edu peer.simobj.path(), peer.name)) 19663109Sstever@eecs.umich.edu raise 19673109Sstever@eecs.umich.edu self.ccConnected = True 19683109Sstever@eecs.umich.edu peer.ccConnected = True 19693109Sstever@eecs.umich.edu 19703109Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a 19713109Sstever@eecs.umich.edu# PortRef, but has an index. 19723109Sstever@eecs.umich.educlass VectorPortElementRef(PortRef): 19733109Sstever@eecs.umich.edu def __init__(self, simobj, name, role, index): 19743105Sstever@eecs.umich.edu PortRef.__init__(self, simobj, name, role) 19753105Sstever@eecs.umich.edu self.index = index 19763105Sstever@eecs.umich.edu 19773105Sstever@eecs.umich.edu def __str__(self): 19783105Sstever@eecs.umich.edu return '%s.%s[%d]' % (self.simobj, self.name, self.index) 19793105Sstever@eecs.umich.edu 19803105Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element). 19813101Sstever@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances. 19823101Sstever@eecs.umich.educlass VectorPortRef(object): 19833101Sstever@eecs.umich.edu def __init__(self, simobj, name, role): 19843101Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 19853101Sstever@eecs.umich.edu self.simobj = simobj 19863101Sstever@eecs.umich.edu self.name = name 19873105Sstever@eecs.umich.edu self.role = role 19888839Sandreas.hansson@arm.com self.elements = [] 19893101Sstever@eecs.umich.edu 19903101Sstever@eecs.umich.edu def __str__(self): 19913101Sstever@eecs.umich.edu return '%s.%s[:]' % (self.simobj, self.name) 19923105Sstever@eecs.umich.edu 19933105Sstever@eecs.umich.edu def __len__(self): 19943101Sstever@eecs.umich.edu # Return the number of connected peers, corresponding the the 19958840Sandreas.hansson@arm.com # length of the elements. 19968840Sandreas.hansson@arm.com return len(self.elements) 19978840Sandreas.hansson@arm.com 19988840Sandreas.hansson@arm.com # for config.ini, print peer's name (not ours) 19998840Sandreas.hansson@arm.com def ini_str(self): 200011988Sandreas.sandberg@arm.com return ' '.join([el.ini_str() for el in self.elements]) 200111988Sandreas.sandberg@arm.com 200211988Sandreas.sandberg@arm.com # for config.json 20038840Sandreas.hansson@arm.com def get_config_as_dict(self): 20048840Sandreas.hansson@arm.com return {'role' : self.role, 20058840Sandreas.hansson@arm.com 'peer' : [el.ini_str() for el in self.elements]} 20068840Sandreas.hansson@arm.com 20078840Sandreas.hansson@arm.com def __getitem__(self, key): 20088840Sandreas.hansson@arm.com if not isinstance(key, int): 20098839Sandreas.hansson@arm.com raise TypeError("VectorPort index must be integer") 20108839Sandreas.hansson@arm.com if key >= len(self.elements): 20118839Sandreas.hansson@arm.com # need to extend list 20128839Sandreas.hansson@arm.com ext = [VectorPortElementRef(self.simobj, self.name, self.role, i) 20138839Sandreas.hansson@arm.com for i in range(len(self.elements), key+1)] 20148839Sandreas.hansson@arm.com self.elements.extend(ext) 20158839Sandreas.hansson@arm.com return self.elements[key] 20168839Sandreas.hansson@arm.com 20178839Sandreas.hansson@arm.com def _get_next(self): 20188839Sandreas.hansson@arm.com return self[len(self.elements)] 20198839Sandreas.hansson@arm.com 20208839Sandreas.hansson@arm.com def __setitem__(self, key, value): 20218839Sandreas.hansson@arm.com if not isinstance(key, int): 20228839Sandreas.hansson@arm.com raise TypeError("VectorPort index must be integer") 20238839Sandreas.hansson@arm.com self[key].connect(value) 20248839Sandreas.hansson@arm.com 20258839Sandreas.hansson@arm.com def connect(self, other): 20268839Sandreas.hansson@arm.com if isinstance(other, (list, tuple)): 20273101Sstever@eecs.umich.edu # Assign list of port refs to vector port. 202810405Sandreas.hansson@arm.com # For now, append them... not sure if that's the right semantics 20293101Sstever@eecs.umich.edu # or if it should replace the current vector. 20303105Sstever@eecs.umich.edu for ref in other: 20313101Sstever@eecs.umich.edu self._get_next().connect(ref) 20323101Sstever@eecs.umich.edu else: 20333105Sstever@eecs.umich.edu # scalar assignment to plain VectorPort is implicit append 20348839Sandreas.hansson@arm.com self._get_next().connect(other) 20358839Sandreas.hansson@arm.com 20368839Sandreas.hansson@arm.com def clone(self, simobj, memo): 20378839Sandreas.hansson@arm.com if self in memo: 20388839Sandreas.hansson@arm.com return memo[self] 20398839Sandreas.hansson@arm.com newRef = copy.copy(self) 20408839Sandreas.hansson@arm.com memo[self] = newRef 20418839Sandreas.hansson@arm.com newRef.simobj = simobj 20428839Sandreas.hansson@arm.com assert(isSimObject(newRef.simobj)) 20438839Sandreas.hansson@arm.com newRef.elements = [el.clone(simobj, memo) for el in self.elements] 20448839Sandreas.hansson@arm.com return newRef 20458839Sandreas.hansson@arm.com 20468839Sandreas.hansson@arm.com def unproxy(self, simobj): 20478839Sandreas.hansson@arm.com [el.unproxy(simobj) for el in self.elements] 20488839Sandreas.hansson@arm.com 20498839Sandreas.hansson@arm.com def ccConnect(self): 20508839Sandreas.hansson@arm.com [el.ccConnect() for el in self.elements] 20518839Sandreas.hansson@arm.com 20528839Sandreas.hansson@arm.com# Port description object. Like a ParamDesc object, this represents a 20538839Sandreas.hansson@arm.com# logical port in the SimObject class, not a particular port on a 20548839Sandreas.hansson@arm.com# SimObject instance. The latter are represented by PortRef objects. 20553105Sstever@eecs.umich.educlass Port(object): 20563109Sstever@eecs.umich.edu # Generate a PortRef for this port on the given SimObject with the 20573109Sstever@eecs.umich.edu # given name 20583109Sstever@eecs.umich.edu def makeRef(self, simobj): 20593109Sstever@eecs.umich.edu return PortRef(simobj, self.name, self.role) 20603109Sstever@eecs.umich.edu 20613109Sstever@eecs.umich.edu # Connect an instance of this port (on the given SimObject with 20623109Sstever@eecs.umich.edu # the given name) with the port described by the supplied PortRef 20633109Sstever@eecs.umich.edu def connect(self, simobj, ref): 20643105Sstever@eecs.umich.edu self.makeRef(simobj).connect(ref) 20656654Snate@binkert.org 20666654Snate@binkert.org # No need for any pre-declarations at the moment as we merely rely 20676654Snate@binkert.org # on an unsigned int. 20686654Snate@binkert.org def cxx_predecls(self, code): 20696654Snate@binkert.org pass 20706654Snate@binkert.org 20716654Snate@binkert.org def pybind_predecls(self, code): 20726654Snate@binkert.org cls.cxx_predecls(self, code) 20736654Snate@binkert.org 20743101Sstever@eecs.umich.edu # Declare an unsigned int with the same name as the port, that 20753101Sstever@eecs.umich.edu # will eventually hold the number of connected ports (and thus the 20763101Sstever@eecs.umich.edu # number of elements for a VectorPort). 20773101Sstever@eecs.umich.edu def cxx_decl(self, code): 20783101Sstever@eecs.umich.edu code('unsigned int port_${{self.name}}_connection_count;') 20793101Sstever@eecs.umich.edu 20807777Sgblack@eecs.umich.educlass MasterPort(Port): 20813101Sstever@eecs.umich.edu # MasterPort("description") 20829827Sakash.bagdia@arm.com def __init__(self, *args): 20833101Sstever@eecs.umich.edu if len(args) == 1: 20849232Sandreas.hansson@arm.com self.desc = args[0] 20853101Sstever@eecs.umich.edu self.role = 'MASTER' 20863885Sbinkertn@umich.edu else: 20873102Sstever@eecs.umich.edu raise TypeError('wrong number of arguments') 20888839Sandreas.hansson@arm.com 20898839Sandreas.hansson@arm.comclass SlavePort(Port): 20906654Snate@binkert.org # SlavePort("description") 20916654Snate@binkert.org def __init__(self, *args): 2092 if len(args) == 1: 2093 self.desc = args[0] 2094 self.role = 'SLAVE' 2095 else: 2096 raise TypeError('wrong number of arguments') 2097 2098# VectorPort description object. Like Port, but represents a vector 2099# of connections (e.g., as on a XBar). 2100class VectorPort(Port): 2101 def __init__(self, *args): 2102 self.isVec = True 2103 2104 def makeRef(self, simobj): 2105 return VectorPortRef(simobj, self.name, self.role) 2106 2107class VectorMasterPort(VectorPort): 2108 # VectorMasterPort("description") 2109 def __init__(self, *args): 2110 if len(args) == 1: 2111 self.desc = args[0] 2112 self.role = 'MASTER' 2113 VectorPort.__init__(self, *args) 2114 else: 2115 raise TypeError('wrong number of arguments') 2116 2117class VectorSlavePort(VectorPort): 2118 # VectorSlavePort("description") 2119 def __init__(self, *args): 2120 if len(args) == 1: 2121 self.desc = args[0] 2122 self.role = 'SLAVE' 2123 VectorPort.__init__(self, *args) 2124 else: 2125 raise TypeError('wrong number of arguments') 2126 2127# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 2128# proxy objects (via set_param_desc()) so that proxy error messages 2129# make sense. 2130class PortParamDesc(object): 2131 __metaclass__ = Singleton 2132 2133 ptype_str = 'Port' 2134 ptype = Port 2135 2136baseEnums = allEnums.copy() 2137baseParams = allParams.copy() 2138 2139def clear(): 2140 global allEnums, allParams 2141 2142 allEnums = baseEnums.copy() 2143 allParams = baseParams.copy() 2144 2145__all__ = ['Param', 'VectorParam', 2146 'Enum', 'ScopedEnum', 'Bool', 'String', 'Float', 2147 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 2148 'Int32', 'UInt32', 'Int64', 'UInt64', 2149 'Counter', 'Addr', 'Tick', 'Percent', 2150 'TcpPort', 'UdpPort', 'EthernetAddr', 2151 'IpAddress', 'IpNetmask', 'IpWithPort', 2152 'MemorySize', 'MemorySize32', 2153 'Latency', 'Frequency', 'Clock', 'Voltage', 'Current', 'Energy', 2154 'NetworkBandwidth', 'MemoryBandwidth', 2155 'AddrRange', 2156 'MaxAddr', 'MaxTick', 'AllMemory', 2157 'Time', 2158 'NextEthernetAddr', 'NULL', 2159 'MasterPort', 'SlavePort', 2160 'VectorMasterPort', 'VectorSlavePort'] 2161 2162from . import SimObject 2163