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