params.py revision 13716
113558Snikos.nikoleris@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 6212563Sgabeblack@google.comfrom __future__ import print_function 6312563Sgabeblack@google.com 643885Sbinkertn@umich.eduimport copy 653885Sbinkertn@umich.eduimport datetime 664762Snate@binkert.orgimport re 673885Sbinkertn@umich.eduimport sys 683885Sbinkertn@umich.eduimport time 697528Ssteve.reinhardt@amd.comimport math 703885Sbinkertn@umich.edu 7113714Sandreas.sandberg@arm.comfrom . import proxy 7213714Sandreas.sandberg@arm.comfrom . import ticks 7313714Sandreas.sandberg@arm.comfrom .util import * 743101Sstever@eecs.umich.edu 754762Snate@binkert.orgdef isSimObject(*args, **kwargs): 7613716Sandreas.sandberg@arm.com from . import SimObject 774762Snate@binkert.org return SimObject.isSimObject(*args, **kwargs) 784762Snate@binkert.org 794762Snate@binkert.orgdef isSimObjectSequence(*args, **kwargs): 8013716Sandreas.sandberg@arm.com from . import SimObject 814762Snate@binkert.org return SimObject.isSimObjectSequence(*args, **kwargs) 824762Snate@binkert.org 834762Snate@binkert.orgdef isSimObjectClass(*args, **kwargs): 8413716Sandreas.sandberg@arm.com from . import SimObject 854762Snate@binkert.org return SimObject.isSimObjectClass(*args, **kwargs) 864762Snate@binkert.org 875033Smilesck@eecs.umich.eduallParams = {} 885033Smilesck@eecs.umich.edu 895033Smilesck@eecs.umich.educlass MetaParamValue(type): 905033Smilesck@eecs.umich.edu def __new__(mcls, name, bases, dct): 915033Smilesck@eecs.umich.edu cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) 925033Smilesck@eecs.umich.edu assert name not in allParams 935033Smilesck@eecs.umich.edu allParams[name] = cls 945033Smilesck@eecs.umich.edu return cls 955033Smilesck@eecs.umich.edu 965033Smilesck@eecs.umich.edu 973101Sstever@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject 983101Sstever@eecs.umich.edu# parameters. 993101Sstever@eecs.umich.educlass ParamValue(object): 1005033Smilesck@eecs.umich.edu __metaclass__ = MetaParamValue 10110267SGeoffrey.Blake@arm.com cmd_line_settable = False 1028596Ssteve.reinhardt@amd.com 1038596Ssteve.reinhardt@amd.com # Generate the code needed as a prerequisite for declaring a C++ 1048596Ssteve.reinhardt@amd.com # object of this type. Typically generates one or more #include 1058596Ssteve.reinhardt@amd.com # statements. Used when declaring parameters of this type. 1067673Snate@binkert.org @classmethod 1077673Snate@binkert.org def cxx_predecls(cls, code): 1087673Snate@binkert.org pass 1097673Snate@binkert.org 11011988Sandreas.sandberg@arm.com @classmethod 11111988Sandreas.sandberg@arm.com def pybind_predecls(cls, code): 11211988Sandreas.sandberg@arm.com cls.cxx_predecls(code) 11311988Sandreas.sandberg@arm.com 1143101Sstever@eecs.umich.edu # default for printing to .ini file is regular string conversion. 1153101Sstever@eecs.umich.edu # will be overridden in some cases 1163101Sstever@eecs.umich.edu def ini_str(self): 1173101Sstever@eecs.umich.edu return str(self) 1183101Sstever@eecs.umich.edu 11910380SAndrew.Bardsley@arm.com # default for printing to .json file is regular string conversion. 12010380SAndrew.Bardsley@arm.com # will be overridden in some cases, mostly to use native Python 12110380SAndrew.Bardsley@arm.com # types where there are similar JSON types 12210380SAndrew.Bardsley@arm.com def config_value(self): 12310380SAndrew.Bardsley@arm.com return str(self) 12410380SAndrew.Bardsley@arm.com 12510458Sandreas.hansson@arm.com # Prerequisites for .ini parsing with cxx_ini_parse 12610458Sandreas.hansson@arm.com @classmethod 12710458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 12810458Sandreas.hansson@arm.com pass 12910458Sandreas.hansson@arm.com 13010458Sandreas.hansson@arm.com # parse a .ini file entry for this param from string expression 13110458Sandreas.hansson@arm.com # src into lvalue dest (of the param's C++ type) 13210458Sandreas.hansson@arm.com @classmethod 13310458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 13410458Sandreas.hansson@arm.com code('// Unhandled param type: %s' % cls.__name__) 13510458Sandreas.hansson@arm.com code('%s false;' % ret) 13610458Sandreas.hansson@arm.com 1373101Sstever@eecs.umich.edu # allows us to blithely call unproxy() on things without checking 1383101Sstever@eecs.umich.edu # if they're really proxies or not 1393101Sstever@eecs.umich.edu def unproxy(self, base): 1403101Sstever@eecs.umich.edu return self 1413101Sstever@eecs.umich.edu 14210267SGeoffrey.Blake@arm.com # Produce a human readable version of the stored value 14310267SGeoffrey.Blake@arm.com def pretty_print(self, value): 14410267SGeoffrey.Blake@arm.com return str(value) 14510267SGeoffrey.Blake@arm.com 1463101Sstever@eecs.umich.edu# Regular parameter description. 1473101Sstever@eecs.umich.educlass ParamDesc(object): 1483101Sstever@eecs.umich.edu def __init__(self, ptype_str, ptype, *args, **kwargs): 1493101Sstever@eecs.umich.edu self.ptype_str = ptype_str 1503101Sstever@eecs.umich.edu # remember ptype only if it is provided 1513101Sstever@eecs.umich.edu if ptype != None: 1523101Sstever@eecs.umich.edu self.ptype = ptype 1533101Sstever@eecs.umich.edu 1543101Sstever@eecs.umich.edu if args: 1553101Sstever@eecs.umich.edu if len(args) == 1: 1563101Sstever@eecs.umich.edu self.desc = args[0] 1573101Sstever@eecs.umich.edu elif len(args) == 2: 1583101Sstever@eecs.umich.edu self.default = args[0] 1593101Sstever@eecs.umich.edu self.desc = args[1] 1603101Sstever@eecs.umich.edu else: 16113663Sandreas.sandberg@arm.com raise TypeError('too many arguments') 1623101Sstever@eecs.umich.edu 16313675Sandreas.sandberg@arm.com if 'desc' in kwargs: 1643101Sstever@eecs.umich.edu assert(not hasattr(self, 'desc')) 1653101Sstever@eecs.umich.edu self.desc = kwargs['desc'] 1663101Sstever@eecs.umich.edu del kwargs['desc'] 1673101Sstever@eecs.umich.edu 16813675Sandreas.sandberg@arm.com if 'default' in kwargs: 1693101Sstever@eecs.umich.edu assert(not hasattr(self, 'default')) 1703101Sstever@eecs.umich.edu self.default = kwargs['default'] 1713101Sstever@eecs.umich.edu del kwargs['default'] 1723101Sstever@eecs.umich.edu 1733101Sstever@eecs.umich.edu if kwargs: 17413663Sandreas.sandberg@arm.com raise TypeError('extra unknown kwargs %s' % kwargs) 1753101Sstever@eecs.umich.edu 1763101Sstever@eecs.umich.edu if not hasattr(self, 'desc'): 17713663Sandreas.sandberg@arm.com raise TypeError('desc attribute missing') 1783101Sstever@eecs.umich.edu 1793101Sstever@eecs.umich.edu def __getattr__(self, attr): 1803101Sstever@eecs.umich.edu if attr == 'ptype': 18113716Sandreas.sandberg@arm.com from . import SimObject 1825033Smilesck@eecs.umich.edu ptype = SimObject.allClasses[self.ptype_str] 1836656Snate@binkert.org assert isSimObjectClass(ptype) 1845033Smilesck@eecs.umich.edu self.ptype = ptype 1855033Smilesck@eecs.umich.edu return ptype 1865033Smilesck@eecs.umich.edu 18713663Sandreas.sandberg@arm.com raise AttributeError("'%s' object has no attribute '%s'" % \ 18813663Sandreas.sandberg@arm.com (type(self).__name__, attr)) 1893101Sstever@eecs.umich.edu 19010267SGeoffrey.Blake@arm.com def example_str(self): 19110267SGeoffrey.Blake@arm.com if hasattr(self.ptype, "ex_str"): 19210267SGeoffrey.Blake@arm.com return self.ptype.ex_str 19310267SGeoffrey.Blake@arm.com else: 19410267SGeoffrey.Blake@arm.com return self.ptype_str 19510267SGeoffrey.Blake@arm.com 19610267SGeoffrey.Blake@arm.com # Is the param available to be exposed on the command line 19710267SGeoffrey.Blake@arm.com def isCmdLineSettable(self): 19810267SGeoffrey.Blake@arm.com if hasattr(self.ptype, "cmd_line_settable"): 19910267SGeoffrey.Blake@arm.com return self.ptype.cmd_line_settable 20010267SGeoffrey.Blake@arm.com else: 20110267SGeoffrey.Blake@arm.com return False 20210267SGeoffrey.Blake@arm.com 2033101Sstever@eecs.umich.edu def convert(self, value): 2043101Sstever@eecs.umich.edu if isinstance(value, proxy.BaseProxy): 2053101Sstever@eecs.umich.edu value.set_param_desc(self) 2063101Sstever@eecs.umich.edu return value 20713699Sandreas.sandberg@arm.com if 'ptype' not in self.__dict__ and isNullPointer(value): 2083101Sstever@eecs.umich.edu # deferred evaluation of SimObject; continue to defer if 2093101Sstever@eecs.umich.edu # we're just assigning a null pointer 2103101Sstever@eecs.umich.edu return value 2113101Sstever@eecs.umich.edu if isinstance(value, self.ptype): 2123101Sstever@eecs.umich.edu return value 2133102Sstever@eecs.umich.edu if isNullPointer(value) and isSimObjectClass(self.ptype): 2143101Sstever@eecs.umich.edu return value 2153101Sstever@eecs.umich.edu return self.ptype(value) 2163101Sstever@eecs.umich.edu 21710267SGeoffrey.Blake@arm.com def pretty_print(self, value): 21810267SGeoffrey.Blake@arm.com if isinstance(value, proxy.BaseProxy): 21910267SGeoffrey.Blake@arm.com return str(value) 22010267SGeoffrey.Blake@arm.com if isNullPointer(value): 22110267SGeoffrey.Blake@arm.com return NULL 22210267SGeoffrey.Blake@arm.com return self.ptype(value).pretty_print(value) 22310267SGeoffrey.Blake@arm.com 2247673Snate@binkert.org def cxx_predecls(self, code): 2258607Sgblack@eecs.umich.edu code('#include <cstddef>') 2267673Snate@binkert.org self.ptype.cxx_predecls(code) 2273101Sstever@eecs.umich.edu 22811988Sandreas.sandberg@arm.com def pybind_predecls(self, code): 22911988Sandreas.sandberg@arm.com self.ptype.pybind_predecls(code) 23011988Sandreas.sandberg@arm.com 2317673Snate@binkert.org def cxx_decl(self, code): 2327673Snate@binkert.org code('${{self.ptype.cxx_type}} ${{self.name}};') 2333101Sstever@eecs.umich.edu 2343101Sstever@eecs.umich.edu# Vector-valued parameter description. Just like ParamDesc, except 2353101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a 2363101Sstever@eecs.umich.edu# single value. 2373101Sstever@eecs.umich.edu 2383101Sstever@eecs.umich.educlass VectorParamValue(list): 2395033Smilesck@eecs.umich.edu __metaclass__ = MetaParamValue 2405475Snate@binkert.org def __setattr__(self, attr, value): 24113663Sandreas.sandberg@arm.com raise AttributeError("Not allowed to set %s on '%s'" % \ 24213663Sandreas.sandberg@arm.com (attr, type(self).__name__)) 2435475Snate@binkert.org 24410380SAndrew.Bardsley@arm.com def config_value(self): 24510380SAndrew.Bardsley@arm.com return [v.config_value() for v in self] 24610380SAndrew.Bardsley@arm.com 2473101Sstever@eecs.umich.edu def ini_str(self): 2483101Sstever@eecs.umich.edu return ' '.join([v.ini_str() for v in self]) 2493101Sstever@eecs.umich.edu 2504762Snate@binkert.org def getValue(self): 2514762Snate@binkert.org return [ v.getValue() for v in self ] 2524762Snate@binkert.org 2533101Sstever@eecs.umich.edu def unproxy(self, base): 25412050Snikos.nikoleris@arm.com if len(self) == 1 and isinstance(self[0], proxy.BaseProxy): 25512050Snikos.nikoleris@arm.com # The value is a proxy (e.g. Parent.any, Parent.all or 25612050Snikos.nikoleris@arm.com # Parent.x) therefore try resolve it 2578459SAli.Saidi@ARM.com return self[0].unproxy(base) 2588459SAli.Saidi@ARM.com else: 25912050Snikos.nikoleris@arm.com return [v.unproxy(base) for v in self] 2603101Sstever@eecs.umich.edu 2617528Ssteve.reinhardt@amd.comclass SimObjectVector(VectorParamValue): 2627528Ssteve.reinhardt@amd.com # support clone operation 2637528Ssteve.reinhardt@amd.com def __call__(self, **kwargs): 2647528Ssteve.reinhardt@amd.com return SimObjectVector([v(**kwargs) for v in self]) 2657528Ssteve.reinhardt@amd.com 2667528Ssteve.reinhardt@amd.com def clear_parent(self, old_parent): 2673101Sstever@eecs.umich.edu for v in self: 2687528Ssteve.reinhardt@amd.com v.clear_parent(old_parent) 2697528Ssteve.reinhardt@amd.com 2707528Ssteve.reinhardt@amd.com def set_parent(self, parent, name): 2717528Ssteve.reinhardt@amd.com if len(self) == 1: 2727528Ssteve.reinhardt@amd.com self[0].set_parent(parent, name) 2737528Ssteve.reinhardt@amd.com else: 2747528Ssteve.reinhardt@amd.com width = int(math.ceil(math.log(len(self))/math.log(10))) 2757528Ssteve.reinhardt@amd.com for i,v in enumerate(self): 2767528Ssteve.reinhardt@amd.com v.set_parent(parent, "%s%0*d" % (name, width, i)) 2777528Ssteve.reinhardt@amd.com 2788321Ssteve.reinhardt@amd.com def has_parent(self): 27912194Sgabeblack@google.com return any([e.has_parent() for e in self if not isNullPointer(e)]) 2807528Ssteve.reinhardt@amd.com 2817528Ssteve.reinhardt@amd.com # return 'cpu0 cpu1' etc. for print_ini() 2827528Ssteve.reinhardt@amd.com def get_name(self): 2837528Ssteve.reinhardt@amd.com return ' '.join([v._name for v in self]) 2847528Ssteve.reinhardt@amd.com 2857528Ssteve.reinhardt@amd.com # By iterating through the constituent members of the vector here 2867528Ssteve.reinhardt@amd.com # we can nicely handle iterating over all a SimObject's children 2877528Ssteve.reinhardt@amd.com # without having to provide lots of special functions on 2887528Ssteve.reinhardt@amd.com # SimObjectVector directly. 2897528Ssteve.reinhardt@amd.com def descendants(self): 2907528Ssteve.reinhardt@amd.com for v in self: 2917528Ssteve.reinhardt@amd.com for obj in v.descendants(): 2927528Ssteve.reinhardt@amd.com yield obj 2933101Sstever@eecs.umich.edu 2948664SAli.Saidi@ARM.com def get_config_as_dict(self): 2958664SAli.Saidi@ARM.com a = [] 2968664SAli.Saidi@ARM.com for v in self: 2978664SAli.Saidi@ARM.com a.append(v.get_config_as_dict()) 2988664SAli.Saidi@ARM.com return a 2998664SAli.Saidi@ARM.com 3009953Sgeoffrey.blake@arm.com # If we are replacing an item in the vector, make sure to set the 3019953Sgeoffrey.blake@arm.com # parent reference of the new SimObject to be the same as the parent 3029953Sgeoffrey.blake@arm.com # of the SimObject being replaced. Useful to have if we created 3039953Sgeoffrey.blake@arm.com # a SimObjectVector of temporary objects that will be modified later in 3049953Sgeoffrey.blake@arm.com # configuration scripts. 3059953Sgeoffrey.blake@arm.com def __setitem__(self, key, value): 3069953Sgeoffrey.blake@arm.com val = self[key] 3079953Sgeoffrey.blake@arm.com if value.has_parent(): 3089953Sgeoffrey.blake@arm.com warn("SimObject %s already has a parent" % value.get_name() +\ 3099953Sgeoffrey.blake@arm.com " that is being overwritten by a SimObjectVector") 3109953Sgeoffrey.blake@arm.com value.set_parent(val.get_parent(), val._name) 3119953Sgeoffrey.blake@arm.com super(SimObjectVector, self).__setitem__(key, value) 3129953Sgeoffrey.blake@arm.com 31310267SGeoffrey.Blake@arm.com # Enumerate the params of each member of the SimObject vector. Creates 31410267SGeoffrey.Blake@arm.com # strings that will allow indexing into the vector by the python code and 31510267SGeoffrey.Blake@arm.com # allow it to be specified on the command line. 31610267SGeoffrey.Blake@arm.com def enumerateParams(self, flags_dict = {}, 31710267SGeoffrey.Blake@arm.com cmd_line_str = "", 31810267SGeoffrey.Blake@arm.com access_str = ""): 31910267SGeoffrey.Blake@arm.com if hasattr(self, "_paramEnumed"): 32012563Sgabeblack@google.com print("Cycle detected enumerating params at %s?!" % (cmd_line_str)) 32110267SGeoffrey.Blake@arm.com else: 32210267SGeoffrey.Blake@arm.com x = 0 32310267SGeoffrey.Blake@arm.com for vals in self: 32410267SGeoffrey.Blake@arm.com # Each entry in the SimObjectVector should be an 32510267SGeoffrey.Blake@arm.com # instance of a SimObject 32610267SGeoffrey.Blake@arm.com flags_dict = vals.enumerateParams(flags_dict, 32710267SGeoffrey.Blake@arm.com cmd_line_str + "%d." % x, 32810267SGeoffrey.Blake@arm.com access_str + "[%d]." % x) 32910267SGeoffrey.Blake@arm.com x = x + 1 33010267SGeoffrey.Blake@arm.com 33110267SGeoffrey.Blake@arm.com return flags_dict 33210267SGeoffrey.Blake@arm.com 3333101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc): 3343101Sstever@eecs.umich.edu # Convert assigned value to appropriate type. If the RHS is not a 3353101Sstever@eecs.umich.edu # list or tuple, it generates a single-element list. 3363101Sstever@eecs.umich.edu def convert(self, value): 3373101Sstever@eecs.umich.edu if isinstance(value, (list, tuple)): 3383101Sstever@eecs.umich.edu # list: coerce each element into new list 3393101Sstever@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) for v in value ] 34010364SGeoffrey.Blake@arm.com elif isinstance(value, str): 34110364SGeoffrey.Blake@arm.com # If input is a csv string 34210364SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) \ 34310364SGeoffrey.Blake@arm.com for v in value.strip('[').strip(']').split(',') ] 3443101Sstever@eecs.umich.edu else: 3454762Snate@binkert.org # singleton: coerce to a single-element list 3464762Snate@binkert.org tmp_list = [ ParamDesc.convert(self, value) ] 3474762Snate@binkert.org 3484762Snate@binkert.org if isSimObjectSequence(tmp_list): 3497528Ssteve.reinhardt@amd.com return SimObjectVector(tmp_list) 3504762Snate@binkert.org else: 3514762Snate@binkert.org return VectorParamValue(tmp_list) 3524762Snate@binkert.org 35310267SGeoffrey.Blake@arm.com # Produce a human readable example string that describes 35410267SGeoffrey.Blake@arm.com # how to set this vector parameter in the absence of a default 35510267SGeoffrey.Blake@arm.com # value. 35610267SGeoffrey.Blake@arm.com def example_str(self): 35710267SGeoffrey.Blake@arm.com s = super(VectorParamDesc, self).example_str() 35810267SGeoffrey.Blake@arm.com help_str = "[" + s + "," + s + ", ...]" 35910267SGeoffrey.Blake@arm.com return help_str 36010267SGeoffrey.Blake@arm.com 36110267SGeoffrey.Blake@arm.com # Produce a human readable representation of the value of this vector param. 36210267SGeoffrey.Blake@arm.com def pretty_print(self, value): 36310267SGeoffrey.Blake@arm.com if isinstance(value, (list, tuple)): 36410267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ] 36510267SGeoffrey.Blake@arm.com elif isinstance(value, str): 36610267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ] 36710267SGeoffrey.Blake@arm.com else: 36810267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, value) ] 36910267SGeoffrey.Blake@arm.com 37010267SGeoffrey.Blake@arm.com return tmp_list 37110267SGeoffrey.Blake@arm.com 37210267SGeoffrey.Blake@arm.com # This is a helper function for the new config system 37310267SGeoffrey.Blake@arm.com def __call__(self, value): 37410267SGeoffrey.Blake@arm.com if isinstance(value, (list, tuple)): 37510267SGeoffrey.Blake@arm.com # list: coerce each element into new list 37610267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) for v in value ] 37710267SGeoffrey.Blake@arm.com elif isinstance(value, str): 37810267SGeoffrey.Blake@arm.com # If input is a csv string 37910364SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) \ 38010364SGeoffrey.Blake@arm.com for v in value.strip('[').strip(']').split(',') ] 38110267SGeoffrey.Blake@arm.com else: 38210267SGeoffrey.Blake@arm.com # singleton: coerce to a single-element list 38310267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, value) ] 38410267SGeoffrey.Blake@arm.com 38510267SGeoffrey.Blake@arm.com return VectorParamValue(tmp_list) 38610267SGeoffrey.Blake@arm.com 3877673Snate@binkert.org def cxx_predecls(self, code): 3887673Snate@binkert.org code('#include <vector>') 3897673Snate@binkert.org self.ptype.cxx_predecls(code) 3903101Sstever@eecs.umich.edu 39111988Sandreas.sandberg@arm.com def pybind_predecls(self, code): 39211988Sandreas.sandberg@arm.com code('#include <vector>') 39311988Sandreas.sandberg@arm.com self.ptype.pybind_predecls(code) 39411988Sandreas.sandberg@arm.com 3957673Snate@binkert.org def cxx_decl(self, code): 3967673Snate@binkert.org code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};') 3973101Sstever@eecs.umich.edu 3983101Sstever@eecs.umich.educlass ParamFactory(object): 3993101Sstever@eecs.umich.edu def __init__(self, param_desc_class, ptype_str = None): 4003101Sstever@eecs.umich.edu self.param_desc_class = param_desc_class 4013101Sstever@eecs.umich.edu self.ptype_str = ptype_str 4023101Sstever@eecs.umich.edu 4033101Sstever@eecs.umich.edu def __getattr__(self, attr): 4043101Sstever@eecs.umich.edu if self.ptype_str: 4053101Sstever@eecs.umich.edu attr = self.ptype_str + '.' + attr 4063101Sstever@eecs.umich.edu return ParamFactory(self.param_desc_class, attr) 4073101Sstever@eecs.umich.edu 4083101Sstever@eecs.umich.edu # E.g., Param.Int(5, "number of widgets") 4093101Sstever@eecs.umich.edu def __call__(self, *args, **kwargs): 4103101Sstever@eecs.umich.edu ptype = None 4113101Sstever@eecs.umich.edu try: 4125033Smilesck@eecs.umich.edu ptype = allParams[self.ptype_str] 4135033Smilesck@eecs.umich.edu except KeyError: 4143101Sstever@eecs.umich.edu # if name isn't defined yet, assume it's a SimObject, and 4153101Sstever@eecs.umich.edu # try to resolve it later 4163101Sstever@eecs.umich.edu pass 4173101Sstever@eecs.umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 4183101Sstever@eecs.umich.edu 4193101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc) 4203101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc) 4213101Sstever@eecs.umich.edu 4223101Sstever@eecs.umich.edu##################################################################### 4233101Sstever@eecs.umich.edu# 4243101Sstever@eecs.umich.edu# Parameter Types 4253101Sstever@eecs.umich.edu# 4263101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types 4273101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more 4283101Sstever@eecs.umich.edu# flexible to define our own set of types. This gives us more control 4293101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the 4303101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via 4313101Sstever@eecs.umich.edu# the __str__() conversion method). 4323101Sstever@eecs.umich.edu# 4333101Sstever@eecs.umich.edu##################################################################### 4343101Sstever@eecs.umich.edu 4353101Sstever@eecs.umich.edu# String-valued parameter. Just mixin the ParamValue class with the 4363101Sstever@eecs.umich.edu# built-in str class. 4373101Sstever@eecs.umich.educlass String(ParamValue,str): 4383101Sstever@eecs.umich.edu cxx_type = 'std::string' 43910267SGeoffrey.Blake@arm.com cmd_line_settable = True 4407673Snate@binkert.org 4417673Snate@binkert.org @classmethod 4427673Snate@binkert.org def cxx_predecls(self, code): 4437673Snate@binkert.org code('#include <string>') 4447673Snate@binkert.org 44510267SGeoffrey.Blake@arm.com def __call__(self, value): 44610267SGeoffrey.Blake@arm.com self = value 44710267SGeoffrey.Blake@arm.com return value 44810267SGeoffrey.Blake@arm.com 44910458Sandreas.hansson@arm.com @classmethod 45010458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 45110458Sandreas.hansson@arm.com code('%s = %s;' % (dest, src)) 45210458Sandreas.hansson@arm.com code('%s true;' % ret) 45310458Sandreas.hansson@arm.com 4544762Snate@binkert.org def getValue(self): 4554762Snate@binkert.org return self 4563101Sstever@eecs.umich.edu 4573101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math 4583101Sstever@eecs.umich.edu# operations in a type-safe way. e.g., a Latency times an int returns 4593101Sstever@eecs.umich.edu# a new Latency object. 4603101Sstever@eecs.umich.educlass NumericParamValue(ParamValue): 46113708Sandreas.sandberg@arm.com @staticmethod 46213708Sandreas.sandberg@arm.com def unwrap(v): 46313708Sandreas.sandberg@arm.com return v.value if isinstance(v, NumericParamValue) else v 46413708Sandreas.sandberg@arm.com 4653101Sstever@eecs.umich.edu def __str__(self): 4663101Sstever@eecs.umich.edu return str(self.value) 4673101Sstever@eecs.umich.edu 4683101Sstever@eecs.umich.edu def __float__(self): 4693101Sstever@eecs.umich.edu return float(self.value) 4703101Sstever@eecs.umich.edu 4713714Sstever@eecs.umich.edu def __long__(self): 4723714Sstever@eecs.umich.edu return long(self.value) 4733714Sstever@eecs.umich.edu 4743714Sstever@eecs.umich.edu def __int__(self): 4753714Sstever@eecs.umich.edu return int(self.value) 4763714Sstever@eecs.umich.edu 4773101Sstever@eecs.umich.edu # hook for bounds checking 4783101Sstever@eecs.umich.edu def _check(self): 4793101Sstever@eecs.umich.edu return 4803101Sstever@eecs.umich.edu 4813101Sstever@eecs.umich.edu def __mul__(self, other): 4823101Sstever@eecs.umich.edu newobj = self.__class__(self) 48313708Sandreas.sandberg@arm.com newobj.value *= NumericParamValue.unwrap(other) 4843101Sstever@eecs.umich.edu newobj._check() 4853101Sstever@eecs.umich.edu return newobj 4863101Sstever@eecs.umich.edu 4873101Sstever@eecs.umich.edu __rmul__ = __mul__ 4883101Sstever@eecs.umich.edu 48913708Sandreas.sandberg@arm.com def __truediv__(self, other): 4903101Sstever@eecs.umich.edu newobj = self.__class__(self) 49113708Sandreas.sandberg@arm.com newobj.value /= NumericParamValue.unwrap(other) 49213708Sandreas.sandberg@arm.com newobj._check() 49313708Sandreas.sandberg@arm.com return newobj 49413708Sandreas.sandberg@arm.com 49513708Sandreas.sandberg@arm.com def __floordiv__(self, other): 49613708Sandreas.sandberg@arm.com newobj = self.__class__(self) 49713708Sandreas.sandberg@arm.com newobj.value //= NumericParamValue.unwrap(other) 49813708Sandreas.sandberg@arm.com newobj._check() 49913708Sandreas.sandberg@arm.com return newobj 50013708Sandreas.sandberg@arm.com 50113708Sandreas.sandberg@arm.com 50213708Sandreas.sandberg@arm.com def __add__(self, other): 50313708Sandreas.sandberg@arm.com newobj = self.__class__(self) 50413708Sandreas.sandberg@arm.com newobj.value += NumericParamValue.unwrap(other) 5053101Sstever@eecs.umich.edu newobj._check() 5063101Sstever@eecs.umich.edu return newobj 5073101Sstever@eecs.umich.edu 5083101Sstever@eecs.umich.edu def __sub__(self, other): 5093101Sstever@eecs.umich.edu newobj = self.__class__(self) 51013708Sandreas.sandberg@arm.com newobj.value -= NumericParamValue.unwrap(other) 5113101Sstever@eecs.umich.edu newobj._check() 5123101Sstever@eecs.umich.edu return newobj 5133101Sstever@eecs.umich.edu 51413708Sandreas.sandberg@arm.com def __iadd__(self, other): 51513708Sandreas.sandberg@arm.com self.value += NumericParamValue.unwrap(other) 51613708Sandreas.sandberg@arm.com self._check() 51713708Sandreas.sandberg@arm.com return self 51813708Sandreas.sandberg@arm.com 51913708Sandreas.sandberg@arm.com def __isub__(self, other): 52013708Sandreas.sandberg@arm.com self.value -= NumericParamValue.unwrap(other) 52113708Sandreas.sandberg@arm.com self._check() 52213708Sandreas.sandberg@arm.com return self 52313708Sandreas.sandberg@arm.com 52413708Sandreas.sandberg@arm.com def __imul__(self, other): 52513708Sandreas.sandberg@arm.com self.value *= NumericParamValue.unwrap(other) 52613708Sandreas.sandberg@arm.com self._check() 52713708Sandreas.sandberg@arm.com return self 52813708Sandreas.sandberg@arm.com 52913708Sandreas.sandberg@arm.com def __itruediv__(self, other): 53013708Sandreas.sandberg@arm.com self.value /= NumericParamValue.unwrap(other) 53113708Sandreas.sandberg@arm.com self._check() 53213708Sandreas.sandberg@arm.com return self 53313708Sandreas.sandberg@arm.com 53413708Sandreas.sandberg@arm.com def __ifloordiv__(self, other): 53513708Sandreas.sandberg@arm.com self.value //= NumericParamValue.unwrap(other) 53613708Sandreas.sandberg@arm.com self._check() 53713708Sandreas.sandberg@arm.com return self 53813708Sandreas.sandberg@arm.com 53913708Sandreas.sandberg@arm.com def __lt__(self, other): 54013708Sandreas.sandberg@arm.com return self.value < NumericParamValue.unwrap(other) 54113708Sandreas.sandberg@arm.com 54213708Sandreas.sandberg@arm.com # Python 2.7 pre __future__.division operators 54313708Sandreas.sandberg@arm.com # TODO: Remove these when after "import division from __future__" 54413708Sandreas.sandberg@arm.com __div__ = __truediv__ 54513708Sandreas.sandberg@arm.com __idiv__ = __itruediv__ 54613708Sandreas.sandberg@arm.com 54710380SAndrew.Bardsley@arm.com def config_value(self): 54810380SAndrew.Bardsley@arm.com return self.value 54910380SAndrew.Bardsley@arm.com 55010458Sandreas.hansson@arm.com @classmethod 55110458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 55210458Sandreas.hansson@arm.com # Assume that base/str.hh will be included anyway 55310458Sandreas.hansson@arm.com # code('#include "base/str.hh"') 55410458Sandreas.hansson@arm.com pass 55510458Sandreas.hansson@arm.com 55610458Sandreas.hansson@arm.com # The default for parsing PODs from an .ini entry is to extract from an 55710458Sandreas.hansson@arm.com # istringstream and let overloading choose the right type according to 55810458Sandreas.hansson@arm.com # the dest type. 55910458Sandreas.hansson@arm.com @classmethod 56010458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 56110458Sandreas.hansson@arm.com code('%s to_number(%s, %s);' % (ret, src, dest)) 56210458Sandreas.hansson@arm.com 5633101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters. See CheckedInt. 5645033Smilesck@eecs.umich.educlass CheckedIntType(MetaParamValue): 5653101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 5663101Sstever@eecs.umich.edu super(CheckedIntType, cls).__init__(name, bases, dict) 5673101Sstever@eecs.umich.edu 5683101Sstever@eecs.umich.edu # CheckedInt is an abstract base class, so we actually don't 5693101Sstever@eecs.umich.edu # want to do any processing on it... the rest of this code is 5703101Sstever@eecs.umich.edu # just for classes that derive from CheckedInt. 5713101Sstever@eecs.umich.edu if name == 'CheckedInt': 5723101Sstever@eecs.umich.edu return 5733101Sstever@eecs.umich.edu 5743101Sstever@eecs.umich.edu if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 5753101Sstever@eecs.umich.edu if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 5763101Sstever@eecs.umich.edu panic("CheckedInt subclass %s must define either\n" \ 5775822Ssaidi@eecs.umich.edu " 'min' and 'max' or 'size' and 'unsigned'\n", 5785822Ssaidi@eecs.umich.edu name); 5793101Sstever@eecs.umich.edu if cls.unsigned: 5803101Sstever@eecs.umich.edu cls.min = 0 5813101Sstever@eecs.umich.edu cls.max = 2 ** cls.size - 1 5823101Sstever@eecs.umich.edu else: 5833101Sstever@eecs.umich.edu cls.min = -(2 ** (cls.size - 1)) 5843101Sstever@eecs.umich.edu cls.max = (2 ** (cls.size - 1)) - 1 5853101Sstever@eecs.umich.edu 5863101Sstever@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters. This 5873101Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific 5883101Sstever@eecs.umich.edu# bounds. Initialization of the min and max bounds is done in the 5893101Sstever@eecs.umich.edu# metaclass CheckedIntType.__init__. 5903101Sstever@eecs.umich.educlass CheckedInt(NumericParamValue): 5913101Sstever@eecs.umich.edu __metaclass__ = CheckedIntType 59210267SGeoffrey.Blake@arm.com cmd_line_settable = True 5933101Sstever@eecs.umich.edu 5943101Sstever@eecs.umich.edu def _check(self): 5953101Sstever@eecs.umich.edu if not self.min <= self.value <= self.max: 59613663Sandreas.sandberg@arm.com raise TypeError('Integer param out of bounds %d < %d < %d' % \ 59713663Sandreas.sandberg@arm.com (self.min, self.value, self.max)) 5983101Sstever@eecs.umich.edu 5993101Sstever@eecs.umich.edu def __init__(self, value): 6003101Sstever@eecs.umich.edu if isinstance(value, str): 6013102Sstever@eecs.umich.edu self.value = convert.toInteger(value) 6023714Sstever@eecs.umich.edu elif isinstance(value, (int, long, float, NumericParamValue)): 6033101Sstever@eecs.umich.edu self.value = long(value) 6043714Sstever@eecs.umich.edu else: 60513663Sandreas.sandberg@arm.com raise TypeError("Can't convert object of type %s to CheckedInt" \ 60613663Sandreas.sandberg@arm.com % type(value).__name__) 6073101Sstever@eecs.umich.edu self._check() 6083101Sstever@eecs.umich.edu 60910267SGeoffrey.Blake@arm.com def __call__(self, value): 61010267SGeoffrey.Blake@arm.com self.__init__(value) 61110267SGeoffrey.Blake@arm.com return value 61210267SGeoffrey.Blake@arm.com 61313711Sandreas.sandberg@arm.com def __index__(self): 61413711Sandreas.sandberg@arm.com return int(self.value) 61513711Sandreas.sandberg@arm.com 6167673Snate@binkert.org @classmethod 6177673Snate@binkert.org def cxx_predecls(cls, code): 6187673Snate@binkert.org # most derived types require this, so we just do it here once 6197673Snate@binkert.org code('#include "base/types.hh"') 6207673Snate@binkert.org 6214762Snate@binkert.org def getValue(self): 6224762Snate@binkert.org return long(self.value) 6234762Snate@binkert.org 6243101Sstever@eecs.umich.educlass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 6253101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 6263101Sstever@eecs.umich.edu 6273101Sstever@eecs.umich.educlass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 6283101Sstever@eecs.umich.educlass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 6293101Sstever@eecs.umich.educlass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 6303101Sstever@eecs.umich.educlass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 6313101Sstever@eecs.umich.educlass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 6323101Sstever@eecs.umich.educlass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 6333101Sstever@eecs.umich.educlass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 6343101Sstever@eecs.umich.educlass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 6353101Sstever@eecs.umich.edu 6363101Sstever@eecs.umich.educlass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 6373101Sstever@eecs.umich.educlass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 6383101Sstever@eecs.umich.educlass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 6393101Sstever@eecs.umich.educlass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 6403101Sstever@eecs.umich.edu 6413101Sstever@eecs.umich.educlass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 6423101Sstever@eecs.umich.edu 6439184Sandreas.hansson@arm.comclass Cycles(CheckedInt): 6449184Sandreas.hansson@arm.com cxx_type = 'Cycles' 6459184Sandreas.hansson@arm.com size = 64 6469184Sandreas.hansson@arm.com unsigned = True 6479184Sandreas.hansson@arm.com 6489184Sandreas.hansson@arm.com def getValue(self): 64911802Sandreas.sandberg@arm.com from _m5.core import Cycles 6509184Sandreas.hansson@arm.com return Cycles(self.value) 6519184Sandreas.hansson@arm.com 65210458Sandreas.hansson@arm.com @classmethod 65310458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 65410458Sandreas.hansson@arm.com # Assume that base/str.hh will be included anyway 65510458Sandreas.hansson@arm.com # code('#include "base/str.hh"') 65610458Sandreas.hansson@arm.com pass 65710458Sandreas.hansson@arm.com 65810458Sandreas.hansson@arm.com @classmethod 65910458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 66010458Sandreas.hansson@arm.com code('uint64_t _temp;') 66110458Sandreas.hansson@arm.com code('bool _ret = to_number(%s, _temp);' % src) 66210458Sandreas.hansson@arm.com code('if (_ret)') 66310458Sandreas.hansson@arm.com code(' %s = Cycles(_temp);' % dest) 66410458Sandreas.hansson@arm.com code('%s _ret;' % ret) 66510458Sandreas.hansson@arm.com 6663101Sstever@eecs.umich.educlass Float(ParamValue, float): 6674446Sbinkertn@umich.edu cxx_type = 'double' 66810668SGeoffrey.Blake@arm.com cmd_line_settable = True 6693101Sstever@eecs.umich.edu 6705468Snate@binkert.org def __init__(self, value): 67110267SGeoffrey.Blake@arm.com if isinstance(value, (int, long, float, NumericParamValue, Float, str)): 6725468Snate@binkert.org self.value = float(value) 6735468Snate@binkert.org else: 67413663Sandreas.sandberg@arm.com raise TypeError("Can't convert object of type %s to Float" \ 67513663Sandreas.sandberg@arm.com % type(value).__name__) 6765468Snate@binkert.org 67710267SGeoffrey.Blake@arm.com def __call__(self, value): 67810267SGeoffrey.Blake@arm.com self.__init__(value) 67910267SGeoffrey.Blake@arm.com return value 68010267SGeoffrey.Blake@arm.com 6814762Snate@binkert.org def getValue(self): 6824762Snate@binkert.org return float(self.value) 6834762Snate@binkert.org 68410380SAndrew.Bardsley@arm.com def config_value(self): 68510380SAndrew.Bardsley@arm.com return self 68610380SAndrew.Bardsley@arm.com 68710458Sandreas.hansson@arm.com @classmethod 68810458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 68910458Sandreas.hansson@arm.com code('#include <sstream>') 69010458Sandreas.hansson@arm.com 69110458Sandreas.hansson@arm.com @classmethod 69210458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 69310458Sandreas.hansson@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 69410458Sandreas.hansson@arm.com 6953101Sstever@eecs.umich.educlass MemorySize(CheckedInt): 6963101Sstever@eecs.umich.edu cxx_type = 'uint64_t' 69710267SGeoffrey.Blake@arm.com ex_str = '512MB' 6983101Sstever@eecs.umich.edu size = 64 6993101Sstever@eecs.umich.edu unsigned = True 7003101Sstever@eecs.umich.edu def __init__(self, value): 7013101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 7023101Sstever@eecs.umich.edu self.value = value.value 7033101Sstever@eecs.umich.edu else: 7043102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 7053101Sstever@eecs.umich.edu self._check() 7063101Sstever@eecs.umich.edu 7073101Sstever@eecs.umich.educlass MemorySize32(CheckedInt): 7084168Sbinkertn@umich.edu cxx_type = 'uint32_t' 70910267SGeoffrey.Blake@arm.com ex_str = '512MB' 7103101Sstever@eecs.umich.edu size = 32 7113101Sstever@eecs.umich.edu unsigned = True 7123101Sstever@eecs.umich.edu def __init__(self, value): 7133101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 7143101Sstever@eecs.umich.edu self.value = value.value 7153101Sstever@eecs.umich.edu else: 7163102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 7173101Sstever@eecs.umich.edu self._check() 7183101Sstever@eecs.umich.edu 7193101Sstever@eecs.umich.educlass Addr(CheckedInt): 7203101Sstever@eecs.umich.edu cxx_type = 'Addr' 7213101Sstever@eecs.umich.edu size = 64 7223101Sstever@eecs.umich.edu unsigned = True 7233101Sstever@eecs.umich.edu def __init__(self, value): 7243101Sstever@eecs.umich.edu if isinstance(value, Addr): 7253101Sstever@eecs.umich.edu self.value = value.value 7263101Sstever@eecs.umich.edu else: 7273101Sstever@eecs.umich.edu try: 72810317Smitch.hayenga@arm.com # Often addresses are referred to with sizes. Ex: A device 72910317Smitch.hayenga@arm.com # base address is at "512MB". Use toMemorySize() to convert 73010317Smitch.hayenga@arm.com # these into addresses. If the address is not specified with a 73110317Smitch.hayenga@arm.com # "size", an exception will occur and numeric translation will 73210317Smitch.hayenga@arm.com # proceed below. 7333102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 73410317Smitch.hayenga@arm.com except (TypeError, ValueError): 73510317Smitch.hayenga@arm.com # Convert number to string and use long() to do automatic 73610317Smitch.hayenga@arm.com # base conversion (requires base=0 for auto-conversion) 73710317Smitch.hayenga@arm.com self.value = long(str(value), base=0) 73810317Smitch.hayenga@arm.com 7393101Sstever@eecs.umich.edu self._check() 7403584Ssaidi@eecs.umich.edu def __add__(self, other): 7413584Ssaidi@eecs.umich.edu if isinstance(other, Addr): 7423584Ssaidi@eecs.umich.edu return self.value + other.value 7433584Ssaidi@eecs.umich.edu else: 7443584Ssaidi@eecs.umich.edu return self.value + other 74510267SGeoffrey.Blake@arm.com def pretty_print(self, value): 74610267SGeoffrey.Blake@arm.com try: 74710267SGeoffrey.Blake@arm.com val = convert.toMemorySize(value) 74810267SGeoffrey.Blake@arm.com except TypeError: 74910267SGeoffrey.Blake@arm.com val = long(value) 75010267SGeoffrey.Blake@arm.com return "0x%x" % long(val) 7513101Sstever@eecs.umich.edu 7529232Sandreas.hansson@arm.comclass AddrRange(ParamValue): 7539235Sandreas.hansson@arm.com cxx_type = 'AddrRange' 7543101Sstever@eecs.umich.edu 7553101Sstever@eecs.umich.edu def __init__(self, *args, **kwargs): 75610676Sandreas.hansson@arm.com # Disable interleaving and hashing by default 7579411Sandreas.hansson@arm.com self.intlvHighBit = 0 75810676Sandreas.hansson@arm.com self.xorHighBit = 0 7599411Sandreas.hansson@arm.com self.intlvBits = 0 7609411Sandreas.hansson@arm.com self.intlvMatch = 0 7619411Sandreas.hansson@arm.com 7623101Sstever@eecs.umich.edu def handle_kwargs(self, kwargs): 7639411Sandreas.hansson@arm.com # An address range needs to have an upper limit, specified 7649411Sandreas.hansson@arm.com # either explicitly with an end, or as an offset using the 7659411Sandreas.hansson@arm.com # size keyword. 7663101Sstever@eecs.umich.edu if 'end' in kwargs: 7679232Sandreas.hansson@arm.com self.end = Addr(kwargs.pop('end')) 7683101Sstever@eecs.umich.edu elif 'size' in kwargs: 7699232Sandreas.hansson@arm.com self.end = self.start + Addr(kwargs.pop('size')) - 1 7703101Sstever@eecs.umich.edu else: 77113663Sandreas.sandberg@arm.com raise TypeError("Either end or size must be specified") 7723101Sstever@eecs.umich.edu 7739411Sandreas.hansson@arm.com # Now on to the optional bit 7749411Sandreas.hansson@arm.com if 'intlvHighBit' in kwargs: 7759411Sandreas.hansson@arm.com self.intlvHighBit = int(kwargs.pop('intlvHighBit')) 77610676Sandreas.hansson@arm.com if 'xorHighBit' in kwargs: 77710676Sandreas.hansson@arm.com self.xorHighBit = int(kwargs.pop('xorHighBit')) 7789411Sandreas.hansson@arm.com if 'intlvBits' in kwargs: 7799411Sandreas.hansson@arm.com self.intlvBits = int(kwargs.pop('intlvBits')) 7809411Sandreas.hansson@arm.com if 'intlvMatch' in kwargs: 7819411Sandreas.hansson@arm.com self.intlvMatch = int(kwargs.pop('intlvMatch')) 7829411Sandreas.hansson@arm.com 7833101Sstever@eecs.umich.edu if len(args) == 0: 7849232Sandreas.hansson@arm.com self.start = Addr(kwargs.pop('start')) 7853101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 7863101Sstever@eecs.umich.edu 7873101Sstever@eecs.umich.edu elif len(args) == 1: 7883101Sstever@eecs.umich.edu if kwargs: 7899232Sandreas.hansson@arm.com self.start = Addr(args[0]) 7903101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 7915219Ssaidi@eecs.umich.edu elif isinstance(args[0], (list, tuple)): 7929232Sandreas.hansson@arm.com self.start = Addr(args[0][0]) 7939232Sandreas.hansson@arm.com self.end = Addr(args[0][1]) 7943101Sstever@eecs.umich.edu else: 7959232Sandreas.hansson@arm.com self.start = Addr(0) 7969232Sandreas.hansson@arm.com self.end = Addr(args[0]) - 1 7973101Sstever@eecs.umich.edu 7983101Sstever@eecs.umich.edu elif len(args) == 2: 7999232Sandreas.hansson@arm.com self.start = Addr(args[0]) 8009232Sandreas.hansson@arm.com self.end = Addr(args[1]) 8013101Sstever@eecs.umich.edu else: 80213663Sandreas.sandberg@arm.com raise TypeError("Too many arguments specified") 8033101Sstever@eecs.umich.edu 8043101Sstever@eecs.umich.edu if kwargs: 80513663Sandreas.sandberg@arm.com raise TypeError("Too many keywords: %s" % list(kwargs.keys())) 8063101Sstever@eecs.umich.edu 8073101Sstever@eecs.umich.edu def __str__(self): 80811620SMatthew.Poremba@amd.com return '%s:%s:%s:%s:%s:%s' \ 80911620SMatthew.Poremba@amd.com % (self.start, self.end, self.intlvHighBit, self.xorHighBit,\ 81011620SMatthew.Poremba@amd.com self.intlvBits, self.intlvMatch) 8119232Sandreas.hansson@arm.com 8129232Sandreas.hansson@arm.com def size(self): 8139411Sandreas.hansson@arm.com # Divide the size by the size of the interleaving slice 8149411Sandreas.hansson@arm.com return (long(self.end) - long(self.start) + 1) >> self.intlvBits 8153101Sstever@eecs.umich.edu 8167673Snate@binkert.org @classmethod 8177673Snate@binkert.org def cxx_predecls(cls, code): 8189232Sandreas.hansson@arm.com Addr.cxx_predecls(code) 8199235Sandreas.hansson@arm.com code('#include "base/addr_range.hh"') 8207675Snate@binkert.org 8217675Snate@binkert.org @classmethod 82211988Sandreas.sandberg@arm.com def pybind_predecls(cls, code): 82311988Sandreas.sandberg@arm.com Addr.pybind_predecls(code) 82411988Sandreas.sandberg@arm.com code('#include "base/addr_range.hh"') 82511988Sandreas.sandberg@arm.com 82611988Sandreas.sandberg@arm.com @classmethod 82710458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 82810458Sandreas.hansson@arm.com code('#include <sstream>') 82910458Sandreas.hansson@arm.com 83010458Sandreas.hansson@arm.com @classmethod 83110458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 83211620SMatthew.Poremba@amd.com code('uint64_t _start, _end, _intlvHighBit = 0, _xorHighBit = 0;') 83311620SMatthew.Poremba@amd.com code('uint64_t _intlvBits = 0, _intlvMatch = 0;') 83410458Sandreas.hansson@arm.com code('char _sep;') 83510458Sandreas.hansson@arm.com code('std::istringstream _stream(${src});') 83610458Sandreas.hansson@arm.com code('_stream >> _start;') 83710458Sandreas.hansson@arm.com code('_stream.get(_sep);') 83810458Sandreas.hansson@arm.com code('_stream >> _end;') 83911620SMatthew.Poremba@amd.com code('if (!_stream.fail() && !_stream.eof()) {') 84011620SMatthew.Poremba@amd.com code(' _stream.get(_sep);') 84111620SMatthew.Poremba@amd.com code(' _stream >> _intlvHighBit;') 84211620SMatthew.Poremba@amd.com code(' _stream.get(_sep);') 84311620SMatthew.Poremba@amd.com code(' _stream >> _xorHighBit;') 84411620SMatthew.Poremba@amd.com code(' _stream.get(_sep);') 84511620SMatthew.Poremba@amd.com code(' _stream >> _intlvBits;') 84611620SMatthew.Poremba@amd.com code(' _stream.get(_sep);') 84711620SMatthew.Poremba@amd.com code(' _stream >> _intlvMatch;') 84811620SMatthew.Poremba@amd.com code('}') 84910458Sandreas.hansson@arm.com code('bool _ret = !_stream.fail() &&' 85010458Sandreas.hansson@arm.com '_stream.eof() && _sep == \':\';') 85110458Sandreas.hansson@arm.com code('if (_ret)') 85211620SMatthew.Poremba@amd.com code(' ${dest} = AddrRange(_start, _end, _intlvHighBit, \ 85311620SMatthew.Poremba@amd.com _xorHighBit, _intlvBits, _intlvMatch);') 85410458Sandreas.hansson@arm.com code('${ret} _ret;') 85510458Sandreas.hansson@arm.com 8564762Snate@binkert.org def getValue(self): 85711991Sandreas.sandberg@arm.com # Go from the Python class to the wrapped C++ class 85811802Sandreas.sandberg@arm.com from _m5.range import AddrRange 8594762Snate@binkert.org 8609411Sandreas.hansson@arm.com return AddrRange(long(self.start), long(self.end), 86110676Sandreas.hansson@arm.com int(self.intlvHighBit), int(self.xorHighBit), 86210676Sandreas.hansson@arm.com int(self.intlvBits), int(self.intlvMatch)) 8633101Sstever@eecs.umich.edu 8643101Sstever@eecs.umich.edu# Boolean parameter type. Python doesn't let you subclass bool, since 8653101Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and 8663101Sstever@eecs.umich.edu# False. Thus this is a little more complicated than String. 8673101Sstever@eecs.umich.educlass Bool(ParamValue): 8683101Sstever@eecs.umich.edu cxx_type = 'bool' 86910267SGeoffrey.Blake@arm.com cmd_line_settable = True 87010267SGeoffrey.Blake@arm.com 8713101Sstever@eecs.umich.edu def __init__(self, value): 8723101Sstever@eecs.umich.edu try: 8733102Sstever@eecs.umich.edu self.value = convert.toBool(value) 8743101Sstever@eecs.umich.edu except TypeError: 8753101Sstever@eecs.umich.edu self.value = bool(value) 8763101Sstever@eecs.umich.edu 87710267SGeoffrey.Blake@arm.com def __call__(self, value): 87810267SGeoffrey.Blake@arm.com self.__init__(value) 87910267SGeoffrey.Blake@arm.com return value 88010267SGeoffrey.Blake@arm.com 8814762Snate@binkert.org def getValue(self): 8824762Snate@binkert.org return bool(self.value) 8834762Snate@binkert.org 8843101Sstever@eecs.umich.edu def __str__(self): 8853101Sstever@eecs.umich.edu return str(self.value) 8863101Sstever@eecs.umich.edu 8878934SBrad.Beckmann@amd.com # implement truth value testing for Bool parameters so that these params 8888934SBrad.Beckmann@amd.com # evaluate correctly during the python configuration phase 88913697Sandreas.sandberg@arm.com def __bool__(self): 8908934SBrad.Beckmann@amd.com return bool(self.value) 8918934SBrad.Beckmann@amd.com 89213697Sandreas.sandberg@arm.com # Python 2.7 uses __nonzero__ instead of __bool__ 89313697Sandreas.sandberg@arm.com __nonzero__ = __bool__ 89413697Sandreas.sandberg@arm.com 8953101Sstever@eecs.umich.edu def ini_str(self): 8963101Sstever@eecs.umich.edu if self.value: 8973101Sstever@eecs.umich.edu return 'true' 8983101Sstever@eecs.umich.edu return 'false' 8993101Sstever@eecs.umich.edu 90010380SAndrew.Bardsley@arm.com def config_value(self): 90110380SAndrew.Bardsley@arm.com return self.value 90210380SAndrew.Bardsley@arm.com 90310458Sandreas.hansson@arm.com @classmethod 90410458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 90510458Sandreas.hansson@arm.com # Assume that base/str.hh will be included anyway 90610458Sandreas.hansson@arm.com # code('#include "base/str.hh"') 90710458Sandreas.hansson@arm.com pass 90810458Sandreas.hansson@arm.com 90910458Sandreas.hansson@arm.com @classmethod 91010458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 91110458Sandreas.hansson@arm.com code('%s to_bool(%s, %s);' % (ret, src, dest)) 91210458Sandreas.hansson@arm.com 9133101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1): 91413709Sandreas.sandberg@arm.com bytes = [ int(x, 16) for x in addr.split(':') ] 9153101Sstever@eecs.umich.edu bytes[5] += val 9163101Sstever@eecs.umich.edu for i in (5, 4, 3, 2, 1): 9173101Sstever@eecs.umich.edu val,rem = divmod(bytes[i], 256) 9183101Sstever@eecs.umich.edu bytes[i] = rem 9193101Sstever@eecs.umich.edu if val == 0: 9203101Sstever@eecs.umich.edu break 9213101Sstever@eecs.umich.edu bytes[i - 1] += val 9223101Sstever@eecs.umich.edu assert(bytes[0] <= 255) 9233101Sstever@eecs.umich.edu return ':'.join(map(lambda x: '%02x' % x, bytes)) 9243101Sstever@eecs.umich.edu 9254380Sbinkertn@umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 9264380Sbinkertn@umich.edudef NextEthernetAddr(): 9274380Sbinkertn@umich.edu global _NextEthernetAddr 9283101Sstever@eecs.umich.edu 9294380Sbinkertn@umich.edu value = _NextEthernetAddr 9304380Sbinkertn@umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 9314380Sbinkertn@umich.edu return value 9323101Sstever@eecs.umich.edu 9333101Sstever@eecs.umich.educlass EthernetAddr(ParamValue): 9343101Sstever@eecs.umich.edu cxx_type = 'Net::EthAddr' 93510267SGeoffrey.Blake@arm.com ex_str = "00:90:00:00:00:01" 93610267SGeoffrey.Blake@arm.com cmd_line_settable = True 9377673Snate@binkert.org 9387673Snate@binkert.org @classmethod 9397673Snate@binkert.org def cxx_predecls(cls, code): 9407673Snate@binkert.org code('#include "base/inet.hh"') 9417673Snate@binkert.org 9423101Sstever@eecs.umich.edu def __init__(self, value): 9433101Sstever@eecs.umich.edu if value == NextEthernetAddr: 9443101Sstever@eecs.umich.edu self.value = value 9453101Sstever@eecs.umich.edu return 9463101Sstever@eecs.umich.edu 9473101Sstever@eecs.umich.edu if not isinstance(value, str): 94813663Sandreas.sandberg@arm.com raise TypeError("expected an ethernet address and didn't get one") 9493101Sstever@eecs.umich.edu 9503101Sstever@eecs.umich.edu bytes = value.split(':') 9513101Sstever@eecs.umich.edu if len(bytes) != 6: 95213663Sandreas.sandberg@arm.com raise TypeError('invalid ethernet address %s' % value) 9533101Sstever@eecs.umich.edu 9543101Sstever@eecs.umich.edu for byte in bytes: 9559941SGeoffrey.Blake@arm.com if not 0 <= int(byte, base=16) <= 0xff: 95613663Sandreas.sandberg@arm.com raise TypeError('invalid ethernet address %s' % value) 9573101Sstever@eecs.umich.edu 9583101Sstever@eecs.umich.edu self.value = value 9593101Sstever@eecs.umich.edu 96010267SGeoffrey.Blake@arm.com def __call__(self, value): 96110267SGeoffrey.Blake@arm.com self.__init__(value) 96210267SGeoffrey.Blake@arm.com return value 96310267SGeoffrey.Blake@arm.com 9643101Sstever@eecs.umich.edu def unproxy(self, base): 9653101Sstever@eecs.umich.edu if self.value == NextEthernetAddr: 9664380Sbinkertn@umich.edu return EthernetAddr(self.value()) 9673101Sstever@eecs.umich.edu return self 9683101Sstever@eecs.umich.edu 9694762Snate@binkert.org def getValue(self): 97011988Sandreas.sandberg@arm.com from _m5.net import EthAddr 9714762Snate@binkert.org return EthAddr(self.value) 9724762Snate@binkert.org 97311228SAndrew.Bardsley@arm.com def __str__(self): 97411228SAndrew.Bardsley@arm.com return self.value 97511228SAndrew.Bardsley@arm.com 9764380Sbinkertn@umich.edu def ini_str(self): 9774380Sbinkertn@umich.edu return self.value 9783101Sstever@eecs.umich.edu 97910458Sandreas.hansson@arm.com @classmethod 98010458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 98110458Sandreas.hansson@arm.com code('%s = Net::EthAddr(%s);' % (dest, src)) 98210458Sandreas.hansson@arm.com code('%s true;' % ret) 98310458Sandreas.hansson@arm.com 9847777Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of 9857777Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP. 9867777Sgblack@eecs.umich.educlass IpAddress(ParamValue): 9877777Sgblack@eecs.umich.edu cxx_type = 'Net::IpAddress' 98810267SGeoffrey.Blake@arm.com ex_str = "127.0.0.1" 98910267SGeoffrey.Blake@arm.com cmd_line_settable = True 9907777Sgblack@eecs.umich.edu 9917777Sgblack@eecs.umich.edu @classmethod 9927777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 9937777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 9947777Sgblack@eecs.umich.edu 9957777Sgblack@eecs.umich.edu def __init__(self, value): 9967777Sgblack@eecs.umich.edu if isinstance(value, IpAddress): 9977777Sgblack@eecs.umich.edu self.ip = value.ip 9987777Sgblack@eecs.umich.edu else: 9997777Sgblack@eecs.umich.edu try: 10007777Sgblack@eecs.umich.edu self.ip = convert.toIpAddress(value) 10017777Sgblack@eecs.umich.edu except TypeError: 10027777Sgblack@eecs.umich.edu self.ip = long(value) 10037777Sgblack@eecs.umich.edu self.verifyIp() 10047777Sgblack@eecs.umich.edu 100510267SGeoffrey.Blake@arm.com def __call__(self, value): 100610267SGeoffrey.Blake@arm.com self.__init__(value) 100710267SGeoffrey.Blake@arm.com return value 100810267SGeoffrey.Blake@arm.com 10098579Ssteve.reinhardt@amd.com def __str__(self): 10108579Ssteve.reinhardt@amd.com tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)] 10118579Ssteve.reinhardt@amd.com return '%d.%d.%d.%d' % tuple(tup) 10128579Ssteve.reinhardt@amd.com 10138579Ssteve.reinhardt@amd.com def __eq__(self, other): 10148579Ssteve.reinhardt@amd.com if isinstance(other, IpAddress): 10158579Ssteve.reinhardt@amd.com return self.ip == other.ip 10168579Ssteve.reinhardt@amd.com elif isinstance(other, str): 10178579Ssteve.reinhardt@amd.com try: 10188579Ssteve.reinhardt@amd.com return self.ip == convert.toIpAddress(other) 10198579Ssteve.reinhardt@amd.com except: 10208579Ssteve.reinhardt@amd.com return False 10218579Ssteve.reinhardt@amd.com else: 10228579Ssteve.reinhardt@amd.com return self.ip == other 10238579Ssteve.reinhardt@amd.com 10248579Ssteve.reinhardt@amd.com def __ne__(self, other): 10258579Ssteve.reinhardt@amd.com return not (self == other) 10268579Ssteve.reinhardt@amd.com 10277777Sgblack@eecs.umich.edu def verifyIp(self): 10287777Sgblack@eecs.umich.edu if self.ip < 0 or self.ip >= (1 << 32): 102913663Sandreas.sandberg@arm.com raise TypeError("invalid ip address %#08x" % self.ip) 10307777Sgblack@eecs.umich.edu 10317777Sgblack@eecs.umich.edu def getValue(self): 103211988Sandreas.sandberg@arm.com from _m5.net import IpAddress 10337777Sgblack@eecs.umich.edu return IpAddress(self.ip) 10347777Sgblack@eecs.umich.edu 10357777Sgblack@eecs.umich.edu# When initializing an IpNetmask, pass in an existing IpNetmask, a string of 10367777Sgblack@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 10377777Sgblack@eecs.umich.edu# positional or keyword arguments. 10387777Sgblack@eecs.umich.educlass IpNetmask(IpAddress): 10397777Sgblack@eecs.umich.edu cxx_type = 'Net::IpNetmask' 104010267SGeoffrey.Blake@arm.com ex_str = "127.0.0.0/24" 104110267SGeoffrey.Blake@arm.com cmd_line_settable = True 10427777Sgblack@eecs.umich.edu 10437777Sgblack@eecs.umich.edu @classmethod 10447777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 10457777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 10467777Sgblack@eecs.umich.edu 10477777Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 10487777Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 10497777Sgblack@eecs.umich.edu if key in kwargs: 10507777Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 10517777Sgblack@eecs.umich.edu elif elseVal: 10527777Sgblack@eecs.umich.edu setattr(self, key, elseVal) 10537777Sgblack@eecs.umich.edu else: 105413663Sandreas.sandberg@arm.com raise TypeError("No value set for %s" % key) 10557777Sgblack@eecs.umich.edu 10567777Sgblack@eecs.umich.edu if len(args) == 0: 10577777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip') 10587777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask') 10597777Sgblack@eecs.umich.edu 10607777Sgblack@eecs.umich.edu elif len(args) == 1: 10617777Sgblack@eecs.umich.edu if kwargs: 10627777Sgblack@eecs.umich.edu if not 'ip' in kwargs and not 'netmask' in kwargs: 106313663Sandreas.sandberg@arm.com raise TypeError("Invalid arguments") 10647777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 10657777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask', args[0]) 10667777Sgblack@eecs.umich.edu elif isinstance(args[0], IpNetmask): 10677777Sgblack@eecs.umich.edu self.ip = args[0].ip 10687777Sgblack@eecs.umich.edu self.netmask = args[0].netmask 10697777Sgblack@eecs.umich.edu else: 10707777Sgblack@eecs.umich.edu (self.ip, self.netmask) = convert.toIpNetmask(args[0]) 10717777Sgblack@eecs.umich.edu 10727777Sgblack@eecs.umich.edu elif len(args) == 2: 10737777Sgblack@eecs.umich.edu self.ip = args[0] 10747777Sgblack@eecs.umich.edu self.netmask = args[1] 10757777Sgblack@eecs.umich.edu else: 107613663Sandreas.sandberg@arm.com raise TypeError("Too many arguments specified") 10777777Sgblack@eecs.umich.edu 10787777Sgblack@eecs.umich.edu if kwargs: 107913663Sandreas.sandberg@arm.com raise TypeError("Too many keywords: %s" % list(kwargs.keys())) 10807777Sgblack@eecs.umich.edu 10817777Sgblack@eecs.umich.edu self.verify() 10827777Sgblack@eecs.umich.edu 108310267SGeoffrey.Blake@arm.com def __call__(self, value): 108410267SGeoffrey.Blake@arm.com self.__init__(value) 108510267SGeoffrey.Blake@arm.com return value 108610267SGeoffrey.Blake@arm.com 10878579Ssteve.reinhardt@amd.com def __str__(self): 10888579Ssteve.reinhardt@amd.com return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask) 10898579Ssteve.reinhardt@amd.com 10908579Ssteve.reinhardt@amd.com def __eq__(self, other): 10918579Ssteve.reinhardt@amd.com if isinstance(other, IpNetmask): 10928579Ssteve.reinhardt@amd.com return self.ip == other.ip and self.netmask == other.netmask 10938579Ssteve.reinhardt@amd.com elif isinstance(other, str): 10948579Ssteve.reinhardt@amd.com try: 10958579Ssteve.reinhardt@amd.com return (self.ip, self.netmask) == convert.toIpNetmask(other) 10968579Ssteve.reinhardt@amd.com except: 10978579Ssteve.reinhardt@amd.com return False 10988579Ssteve.reinhardt@amd.com else: 10998579Ssteve.reinhardt@amd.com return False 11008579Ssteve.reinhardt@amd.com 11017777Sgblack@eecs.umich.edu def verify(self): 11027777Sgblack@eecs.umich.edu self.verifyIp() 11037777Sgblack@eecs.umich.edu if self.netmask < 0 or self.netmask > 32: 110413663Sandreas.sandberg@arm.com raise TypeError("invalid netmask %d" % netmask) 11057777Sgblack@eecs.umich.edu 11067777Sgblack@eecs.umich.edu def getValue(self): 110711988Sandreas.sandberg@arm.com from _m5.net import IpNetmask 11087777Sgblack@eecs.umich.edu return IpNetmask(self.ip, self.netmask) 11097777Sgblack@eecs.umich.edu 11107777Sgblack@eecs.umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of 11117777Sgblack@eecs.umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments. 11127777Sgblack@eecs.umich.educlass IpWithPort(IpAddress): 11137777Sgblack@eecs.umich.edu cxx_type = 'Net::IpWithPort' 111410267SGeoffrey.Blake@arm.com ex_str = "127.0.0.1:80" 111510267SGeoffrey.Blake@arm.com cmd_line_settable = True 11167777Sgblack@eecs.umich.edu 11177777Sgblack@eecs.umich.edu @classmethod 11187777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 11197777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 11207777Sgblack@eecs.umich.edu 11217777Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 11227777Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 11237777Sgblack@eecs.umich.edu if key in kwargs: 11247777Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 11257777Sgblack@eecs.umich.edu elif elseVal: 11267777Sgblack@eecs.umich.edu setattr(self, key, elseVal) 11277777Sgblack@eecs.umich.edu else: 112813663Sandreas.sandberg@arm.com raise TypeError("No value set for %s" % key) 11297777Sgblack@eecs.umich.edu 11307777Sgblack@eecs.umich.edu if len(args) == 0: 11317777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip') 11327777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'port') 11337777Sgblack@eecs.umich.edu 11347777Sgblack@eecs.umich.edu elif len(args) == 1: 11357777Sgblack@eecs.umich.edu if kwargs: 11367777Sgblack@eecs.umich.edu if not 'ip' in kwargs and not 'port' in kwargs: 113713663Sandreas.sandberg@arm.com raise TypeError("Invalid arguments") 11387777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 11397777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'port', args[0]) 11407777Sgblack@eecs.umich.edu elif isinstance(args[0], IpWithPort): 11417777Sgblack@eecs.umich.edu self.ip = args[0].ip 11427777Sgblack@eecs.umich.edu self.port = args[0].port 11437777Sgblack@eecs.umich.edu else: 11447777Sgblack@eecs.umich.edu (self.ip, self.port) = convert.toIpWithPort(args[0]) 11457777Sgblack@eecs.umich.edu 11467777Sgblack@eecs.umich.edu elif len(args) == 2: 11477777Sgblack@eecs.umich.edu self.ip = args[0] 11487777Sgblack@eecs.umich.edu self.port = args[1] 11497777Sgblack@eecs.umich.edu else: 115013663Sandreas.sandberg@arm.com raise TypeError("Too many arguments specified") 11517777Sgblack@eecs.umich.edu 11527777Sgblack@eecs.umich.edu if kwargs: 115313663Sandreas.sandberg@arm.com raise TypeError("Too many keywords: %s" % list(kwargs.keys())) 11547777Sgblack@eecs.umich.edu 11557777Sgblack@eecs.umich.edu self.verify() 11567777Sgblack@eecs.umich.edu 115710267SGeoffrey.Blake@arm.com def __call__(self, value): 115810267SGeoffrey.Blake@arm.com self.__init__(value) 115910267SGeoffrey.Blake@arm.com return value 116010267SGeoffrey.Blake@arm.com 11618579Ssteve.reinhardt@amd.com def __str__(self): 11628579Ssteve.reinhardt@amd.com return "%s:%d" % (super(IpWithPort, self).__str__(), self.port) 11638579Ssteve.reinhardt@amd.com 11648579Ssteve.reinhardt@amd.com def __eq__(self, other): 11658579Ssteve.reinhardt@amd.com if isinstance(other, IpWithPort): 11668579Ssteve.reinhardt@amd.com return self.ip == other.ip and self.port == other.port 11678579Ssteve.reinhardt@amd.com elif isinstance(other, str): 11688579Ssteve.reinhardt@amd.com try: 11698579Ssteve.reinhardt@amd.com return (self.ip, self.port) == convert.toIpWithPort(other) 11708579Ssteve.reinhardt@amd.com except: 11718579Ssteve.reinhardt@amd.com return False 11728579Ssteve.reinhardt@amd.com else: 11738579Ssteve.reinhardt@amd.com return False 11748579Ssteve.reinhardt@amd.com 11757777Sgblack@eecs.umich.edu def verify(self): 11767777Sgblack@eecs.umich.edu self.verifyIp() 11777777Sgblack@eecs.umich.edu if self.port < 0 or self.port > 0xffff: 117813663Sandreas.sandberg@arm.com raise TypeError("invalid port %d" % self.port) 11797777Sgblack@eecs.umich.edu 11807777Sgblack@eecs.umich.edu def getValue(self): 118111988Sandreas.sandberg@arm.com from _m5.net import IpWithPort 11827777Sgblack@eecs.umich.edu return IpWithPort(self.ip, self.port) 11837777Sgblack@eecs.umich.edu 11843932Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 118510380SAndrew.Bardsley@arm.com "%a %b %d %H:%M:%S %Y", 11863932Sbinkertn@umich.edu "%Y/%m/%d %H:%M:%S", 11873932Sbinkertn@umich.edu "%Y/%m/%d %H:%M", 11883932Sbinkertn@umich.edu "%Y/%m/%d", 11893932Sbinkertn@umich.edu "%m/%d/%Y %H:%M:%S", 11903932Sbinkertn@umich.edu "%m/%d/%Y %H:%M", 11913932Sbinkertn@umich.edu "%m/%d/%Y", 11923932Sbinkertn@umich.edu "%m/%d/%y %H:%M:%S", 11933932Sbinkertn@umich.edu "%m/%d/%y %H:%M", 11943932Sbinkertn@umich.edu "%m/%d/%y"] 11953932Sbinkertn@umich.edu 11963932Sbinkertn@umich.edu 11973885Sbinkertn@umich.edudef parse_time(value): 11983932Sbinkertn@umich.edu from time import gmtime, strptime, struct_time, time 11993932Sbinkertn@umich.edu from datetime import datetime, date 12003885Sbinkertn@umich.edu 12013932Sbinkertn@umich.edu if isinstance(value, struct_time): 12023932Sbinkertn@umich.edu return value 12033932Sbinkertn@umich.edu 12043932Sbinkertn@umich.edu if isinstance(value, (int, long)): 12053932Sbinkertn@umich.edu return gmtime(value) 12063932Sbinkertn@umich.edu 12073932Sbinkertn@umich.edu if isinstance(value, (datetime, date)): 12083932Sbinkertn@umich.edu return value.timetuple() 12093932Sbinkertn@umich.edu 12103932Sbinkertn@umich.edu if isinstance(value, str): 12113932Sbinkertn@umich.edu if value in ('Now', 'Today'): 12123932Sbinkertn@umich.edu return time.gmtime(time.time()) 12133932Sbinkertn@umich.edu 12143932Sbinkertn@umich.edu for format in time_formats: 12153932Sbinkertn@umich.edu try: 12163932Sbinkertn@umich.edu return strptime(value, format) 12173932Sbinkertn@umich.edu except ValueError: 12183932Sbinkertn@umich.edu pass 12193885Sbinkertn@umich.edu 122013663Sandreas.sandberg@arm.com raise ValueError("Could not parse '%s' as a time" % value) 12213885Sbinkertn@umich.edu 12223885Sbinkertn@umich.educlass Time(ParamValue): 12234762Snate@binkert.org cxx_type = 'tm' 12247673Snate@binkert.org 12257673Snate@binkert.org @classmethod 12267673Snate@binkert.org def cxx_predecls(cls, code): 12277673Snate@binkert.org code('#include <time.h>') 12287673Snate@binkert.org 12293885Sbinkertn@umich.edu def __init__(self, value): 12303932Sbinkertn@umich.edu self.value = parse_time(value) 12313885Sbinkertn@umich.edu 123210267SGeoffrey.Blake@arm.com def __call__(self, value): 123310267SGeoffrey.Blake@arm.com self.__init__(value) 123410267SGeoffrey.Blake@arm.com return value 123510267SGeoffrey.Blake@arm.com 12364762Snate@binkert.org def getValue(self): 123711988Sandreas.sandberg@arm.com from _m5.core import tm 123811988Sandreas.sandberg@arm.com import calendar 12394762Snate@binkert.org 124011988Sandreas.sandberg@arm.com return tm.gmtime(calendar.timegm(self.value)) 12414762Snate@binkert.org 12423885Sbinkertn@umich.edu def __str__(self): 12434762Snate@binkert.org return time.asctime(self.value) 12443885Sbinkertn@umich.edu 12453885Sbinkertn@umich.edu def ini_str(self): 12463932Sbinkertn@umich.edu return str(self) 12473885Sbinkertn@umich.edu 12488664SAli.Saidi@ARM.com def get_config_as_dict(self): 124910380SAndrew.Bardsley@arm.com assert false 12508664SAli.Saidi@ARM.com return str(self) 12518664SAli.Saidi@ARM.com 125210458Sandreas.hansson@arm.com @classmethod 125310458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 125410458Sandreas.hansson@arm.com code('#include <time.h>') 125510458Sandreas.hansson@arm.com 125610458Sandreas.hansson@arm.com @classmethod 125710458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 125810458Sandreas.hansson@arm.com code('char *_parse_ret = strptime((${src}).c_str(),') 125910458Sandreas.hansson@arm.com code(' "%a %b %d %H:%M:%S %Y", &(${dest}));') 126010458Sandreas.hansson@arm.com code('${ret} _parse_ret && *_parse_ret == \'\\0\';'); 126110458Sandreas.hansson@arm.com 12623101Sstever@eecs.umich.edu# Enumerated types are a little more complex. The user specifies the 12633101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of 12643101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so). (In the 12653101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index 12663101Sstever@eecs.umich.edu# or the corresponding dictionary value. For now, since we only check 12673101Sstever@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file, 12683101Sstever@eecs.umich.edu# there's not much point in using the dictionary.) 12693101Sstever@eecs.umich.edu 12703101Sstever@eecs.umich.edu# What Enum() must do is generate a new type encapsulating the 12713101Sstever@eecs.umich.edu# provided list/dictionary so that specific values of the parameter 12723101Sstever@eecs.umich.edu# can be instances of that type. We define two hidden internal 12733101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then 12743101Sstever@eecs.umich.edu# derive the new type from the appropriate base class on the fly. 12753101Sstever@eecs.umich.edu 12764762Snate@binkert.orgallEnums = {} 12773101Sstever@eecs.umich.edu# Metaclass for Enum types 12785033Smilesck@eecs.umich.educlass MetaEnum(MetaParamValue): 12794762Snate@binkert.org def __new__(mcls, name, bases, dict): 12804762Snate@binkert.org assert name not in allEnums 12814762Snate@binkert.org 12824762Snate@binkert.org cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 12834762Snate@binkert.org allEnums[name] = cls 12844762Snate@binkert.org return cls 12854762Snate@binkert.org 12863101Sstever@eecs.umich.edu def __init__(cls, name, bases, init_dict): 128713675Sandreas.sandberg@arm.com if 'map' in init_dict: 12883101Sstever@eecs.umich.edu if not isinstance(cls.map, dict): 128913663Sandreas.sandberg@arm.com raise TypeError("Enum-derived class attribute 'map' " \ 129013663Sandreas.sandberg@arm.com "must be of type dict") 12913101Sstever@eecs.umich.edu # build list of value strings from map 129213709Sandreas.sandberg@arm.com cls.vals = list(cls.map.keys()) 12933101Sstever@eecs.umich.edu cls.vals.sort() 129413675Sandreas.sandberg@arm.com elif 'vals' in init_dict: 12953101Sstever@eecs.umich.edu if not isinstance(cls.vals, list): 129613663Sandreas.sandberg@arm.com raise TypeError("Enum-derived class attribute 'vals' " \ 129713663Sandreas.sandberg@arm.com "must be of type list") 12983101Sstever@eecs.umich.edu # build string->value map from vals sequence 12993101Sstever@eecs.umich.edu cls.map = {} 13003101Sstever@eecs.umich.edu for idx,val in enumerate(cls.vals): 13013101Sstever@eecs.umich.edu cls.map[val] = idx 13023101Sstever@eecs.umich.edu else: 130313663Sandreas.sandberg@arm.com raise TypeError("Enum-derived class must define "\ 130413663Sandreas.sandberg@arm.com "attribute 'map' or 'vals'") 13053101Sstever@eecs.umich.edu 130613558Snikos.nikoleris@arm.com if cls.is_class: 130713558Snikos.nikoleris@arm.com cls.cxx_type = '%s' % name 130813558Snikos.nikoleris@arm.com else: 130913558Snikos.nikoleris@arm.com cls.cxx_type = 'Enums::%s' % name 13103101Sstever@eecs.umich.edu 13113101Sstever@eecs.umich.edu super(MetaEnum, cls).__init__(name, bases, init_dict) 13123101Sstever@eecs.umich.edu 13133101Sstever@eecs.umich.edu # Generate C++ class declaration for this enum type. 13143101Sstever@eecs.umich.edu # Note that we wrap the enum in a class/struct to act as a namespace, 13153101Sstever@eecs.umich.edu # so that the enum strings can be brief w/o worrying about collisions. 13167673Snate@binkert.org def cxx_decl(cls, code): 131710201SAndrew.Bardsley@arm.com wrapper_name = cls.wrapper_name 131810201SAndrew.Bardsley@arm.com wrapper = 'struct' if cls.wrapper_is_struct else 'namespace' 131910201SAndrew.Bardsley@arm.com name = cls.__name__ if cls.enum_name is None else cls.enum_name 132010201SAndrew.Bardsley@arm.com idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name) 132110201SAndrew.Bardsley@arm.com 13227673Snate@binkert.org code('''\ 132310201SAndrew.Bardsley@arm.com#ifndef $idem_macro 132410201SAndrew.Bardsley@arm.com#define $idem_macro 13257673Snate@binkert.org 132613558Snikos.nikoleris@arm.com''') 132713558Snikos.nikoleris@arm.com if cls.is_class: 132813558Snikos.nikoleris@arm.com code('''\ 132913558Snikos.nikoleris@arm.comenum class $name { 133013558Snikos.nikoleris@arm.com''') 133113558Snikos.nikoleris@arm.com else: 133213558Snikos.nikoleris@arm.com code('''\ 133310201SAndrew.Bardsley@arm.com$wrapper $wrapper_name { 13347673Snate@binkert.org enum $name { 13357673Snate@binkert.org''') 133613558Snikos.nikoleris@arm.com code.indent(1) 133713558Snikos.nikoleris@arm.com code.indent(1) 13384762Snate@binkert.org for val in cls.vals: 13397673Snate@binkert.org code('$val = ${{cls.map[val]}},') 13408902Sandreas.hansson@arm.com code('Num_$name = ${{len(cls.vals)}}') 134113558Snikos.nikoleris@arm.com code.dedent(1) 134213558Snikos.nikoleris@arm.com code('};') 13434762Snate@binkert.org 134413558Snikos.nikoleris@arm.com if cls.is_class: 134513558Snikos.nikoleris@arm.com code('''\ 134613558Snikos.nikoleris@arm.comextern const char *${name}Strings[static_cast<int>(${name}::Num_${name})]; 134713558Snikos.nikoleris@arm.com''') 134813558Snikos.nikoleris@arm.com elif cls.wrapper_is_struct: 134913558Snikos.nikoleris@arm.com code('static const char *${name}Strings[Num_${name}];') 135010201SAndrew.Bardsley@arm.com else: 135110201SAndrew.Bardsley@arm.com code('extern const char *${name}Strings[Num_${name}];') 135213558Snikos.nikoleris@arm.com 135313558Snikos.nikoleris@arm.com if not cls.is_class: 135413558Snikos.nikoleris@arm.com code.dedent(1) 135513558Snikos.nikoleris@arm.com code('};') 135610201SAndrew.Bardsley@arm.com 135710201SAndrew.Bardsley@arm.com code() 135810201SAndrew.Bardsley@arm.com code('#endif // $idem_macro') 13597673Snate@binkert.org 13607673Snate@binkert.org def cxx_def(cls, code): 136110201SAndrew.Bardsley@arm.com wrapper_name = cls.wrapper_name 136210201SAndrew.Bardsley@arm.com file_name = cls.__name__ 136310201SAndrew.Bardsley@arm.com name = cls.__name__ if cls.enum_name is None else cls.enum_name 136410201SAndrew.Bardsley@arm.com 136510201SAndrew.Bardsley@arm.com code('#include "enums/$file_name.hh"') 136610201SAndrew.Bardsley@arm.com if cls.wrapper_is_struct: 136710201SAndrew.Bardsley@arm.com code('const char *${wrapper_name}::${name}Strings' 136810201SAndrew.Bardsley@arm.com '[Num_${name}] =') 136910201SAndrew.Bardsley@arm.com else: 137013558Snikos.nikoleris@arm.com if cls.is_class: 137113558Snikos.nikoleris@arm.com code('''\ 137213558Snikos.nikoleris@arm.comconst char *${name}Strings[static_cast<int>(${name}::Num_${name})] = 137313558Snikos.nikoleris@arm.com''') 137413558Snikos.nikoleris@arm.com else: 137513558Snikos.nikoleris@arm.com code('namespace Enums {') 137613558Snikos.nikoleris@arm.com code.indent(1) 137713558Snikos.nikoleris@arm.com code('const char *${name}Strings[Num_${name}] =') 137810201SAndrew.Bardsley@arm.com 137910201SAndrew.Bardsley@arm.com code('{') 138010201SAndrew.Bardsley@arm.com code.indent(1) 13814762Snate@binkert.org for val in cls.vals: 13827673Snate@binkert.org code('"$val",') 138310201SAndrew.Bardsley@arm.com code.dedent(1) 138410201SAndrew.Bardsley@arm.com code('};') 138510201SAndrew.Bardsley@arm.com 138613558Snikos.nikoleris@arm.com if not cls.wrapper_is_struct and not cls.is_class: 138713558Snikos.nikoleris@arm.com code.dedent(1) 138810201SAndrew.Bardsley@arm.com code('} // namespace $wrapper_name') 138913558Snikos.nikoleris@arm.com 13903101Sstever@eecs.umich.edu 139111988Sandreas.sandberg@arm.com def pybind_def(cls, code): 139211988Sandreas.sandberg@arm.com name = cls.__name__ 139311988Sandreas.sandberg@arm.com enum_name = cls.__name__ if cls.enum_name is None else cls.enum_name 139413558Snikos.nikoleris@arm.com wrapper_name = enum_name if cls.is_class else cls.wrapper_name 139511988Sandreas.sandberg@arm.com 139611988Sandreas.sandberg@arm.com code('''#include "pybind11/pybind11.h" 139711988Sandreas.sandberg@arm.com#include "pybind11/stl.h" 139811988Sandreas.sandberg@arm.com 139911988Sandreas.sandberg@arm.com#include <sim/init.hh> 140011988Sandreas.sandberg@arm.com 140111988Sandreas.sandberg@arm.comnamespace py = pybind11; 140211988Sandreas.sandberg@arm.com 140311988Sandreas.sandberg@arm.comstatic void 140411988Sandreas.sandberg@arm.commodule_init(py::module &m_internal) 140511988Sandreas.sandberg@arm.com{ 140611988Sandreas.sandberg@arm.com py::module m = m_internal.def_submodule("enum_${name}"); 140711988Sandreas.sandberg@arm.com 140811988Sandreas.sandberg@arm.com''') 140913558Snikos.nikoleris@arm.com if cls.is_class: 141013558Snikos.nikoleris@arm.com code('py::enum_<${enum_name}>(m, "enum_${name}")') 141113558Snikos.nikoleris@arm.com else: 141213558Snikos.nikoleris@arm.com code('py::enum_<${wrapper_name}::${enum_name}>(m, "enum_${name}")') 141311988Sandreas.sandberg@arm.com 141411988Sandreas.sandberg@arm.com code.indent() 141511988Sandreas.sandberg@arm.com code.indent() 141611988Sandreas.sandberg@arm.com for val in cls.vals: 141711988Sandreas.sandberg@arm.com code('.value("${val}", ${wrapper_name}::${val})') 141811988Sandreas.sandberg@arm.com code('.value("Num_${name}", ${wrapper_name}::Num_${enum_name})') 141911988Sandreas.sandberg@arm.com code('.export_values()') 142011988Sandreas.sandberg@arm.com code(';') 142111988Sandreas.sandberg@arm.com code.dedent() 142211988Sandreas.sandberg@arm.com 142311988Sandreas.sandberg@arm.com code('}') 142411988Sandreas.sandberg@arm.com code.dedent() 142511988Sandreas.sandberg@arm.com code() 142611988Sandreas.sandberg@arm.com code('static EmbeddedPyBind embed_enum("enum_${name}", module_init);') 142711988Sandreas.sandberg@arm.com 14288596Ssteve.reinhardt@amd.com 14293101Sstever@eecs.umich.edu# Base class for enum types. 14303101Sstever@eecs.umich.educlass Enum(ParamValue): 14313101Sstever@eecs.umich.edu __metaclass__ = MetaEnum 14323101Sstever@eecs.umich.edu vals = [] 143310267SGeoffrey.Blake@arm.com cmd_line_settable = True 14343101Sstever@eecs.umich.edu 143510201SAndrew.Bardsley@arm.com # The name of the wrapping namespace or struct 143610201SAndrew.Bardsley@arm.com wrapper_name = 'Enums' 143710201SAndrew.Bardsley@arm.com 143810201SAndrew.Bardsley@arm.com # If true, the enum is wrapped in a struct rather than a namespace 143910201SAndrew.Bardsley@arm.com wrapper_is_struct = False 144010201SAndrew.Bardsley@arm.com 144113558Snikos.nikoleris@arm.com is_class = False 144213558Snikos.nikoleris@arm.com 144310201SAndrew.Bardsley@arm.com # If not None, use this as the enum name rather than this class name 144410201SAndrew.Bardsley@arm.com enum_name = None 144510201SAndrew.Bardsley@arm.com 14463101Sstever@eecs.umich.edu def __init__(self, value): 14473101Sstever@eecs.umich.edu if value not in self.map: 144813663Sandreas.sandberg@arm.com raise TypeError("Enum param got bad value '%s' (not in %s)" \ 144913663Sandreas.sandberg@arm.com % (value, self.vals)) 14503101Sstever@eecs.umich.edu self.value = value 14513101Sstever@eecs.umich.edu 145210267SGeoffrey.Blake@arm.com def __call__(self, value): 145310267SGeoffrey.Blake@arm.com self.__init__(value) 145410267SGeoffrey.Blake@arm.com return value 145510267SGeoffrey.Blake@arm.com 14567675Snate@binkert.org @classmethod 14577675Snate@binkert.org def cxx_predecls(cls, code): 14587675Snate@binkert.org code('#include "enums/$0.hh"', cls.__name__) 14597675Snate@binkert.org 14607675Snate@binkert.org @classmethod 146110458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 146210458Sandreas.hansson@arm.com code('if (false) {') 146313709Sandreas.sandberg@arm.com for elem_name in cls.map.keys(): 146410458Sandreas.hansson@arm.com code('} else if (%s == "%s") {' % (src, elem_name)) 146510458Sandreas.hansson@arm.com code.indent() 146610458Sandreas.hansson@arm.com code('%s = Enums::%s;' % (dest, elem_name)) 146710458Sandreas.hansson@arm.com code('%s true;' % ret) 146810458Sandreas.hansson@arm.com code.dedent() 146910458Sandreas.hansson@arm.com code('} else {') 147010458Sandreas.hansson@arm.com code(' %s false;' % ret) 147110458Sandreas.hansson@arm.com code('}') 147210458Sandreas.hansson@arm.com 14734762Snate@binkert.org def getValue(self): 147411988Sandreas.sandberg@arm.com import m5.internal.params 147511988Sandreas.sandberg@arm.com e = getattr(m5.internal.params, "enum_%s" % self.__class__.__name__) 147611988Sandreas.sandberg@arm.com return e(self.map[self.value]) 14774762Snate@binkert.org 14783101Sstever@eecs.umich.edu def __str__(self): 14793101Sstever@eecs.umich.edu return self.value 14803101Sstever@eecs.umich.edu 148113558Snikos.nikoleris@arm.com# This param will generate a scoped c++ enum and its python bindings. 148213558Snikos.nikoleris@arm.comclass ScopedEnum(Enum): 148313558Snikos.nikoleris@arm.com __metaclass__ = MetaEnum 148413558Snikos.nikoleris@arm.com vals = [] 148513558Snikos.nikoleris@arm.com cmd_line_settable = True 148613558Snikos.nikoleris@arm.com 148713558Snikos.nikoleris@arm.com # The name of the wrapping namespace or struct 148813558Snikos.nikoleris@arm.com wrapper_name = None 148913558Snikos.nikoleris@arm.com 149013558Snikos.nikoleris@arm.com # If true, the enum is wrapped in a struct rather than a namespace 149113558Snikos.nikoleris@arm.com wrapper_is_struct = False 149213558Snikos.nikoleris@arm.com 149313558Snikos.nikoleris@arm.com # If true, the generated enum is a scoped enum 149413558Snikos.nikoleris@arm.com is_class = True 149513558Snikos.nikoleris@arm.com 149613558Snikos.nikoleris@arm.com # If not None, use this as the enum name rather than this class name 149713558Snikos.nikoleris@arm.com enum_name = None 149813558Snikos.nikoleris@arm.com 14993101Sstever@eecs.umich.edu# how big does a rounding error need to be before we warn about it? 15003101Sstever@eecs.umich.edufrequency_tolerance = 0.001 # 0.1% 15013101Sstever@eecs.umich.edu 15024167Sbinkertn@umich.educlass TickParamValue(NumericParamValue): 15033101Sstever@eecs.umich.edu cxx_type = 'Tick' 150410267SGeoffrey.Blake@arm.com ex_str = "1MHz" 150510267SGeoffrey.Blake@arm.com cmd_line_settable = True 15067673Snate@binkert.org 15077673Snate@binkert.org @classmethod 15087673Snate@binkert.org def cxx_predecls(cls, code): 15097673Snate@binkert.org code('#include "base/types.hh"') 15107673Snate@binkert.org 151110267SGeoffrey.Blake@arm.com def __call__(self, value): 151210267SGeoffrey.Blake@arm.com self.__init__(value) 151310267SGeoffrey.Blake@arm.com return value 151410267SGeoffrey.Blake@arm.com 15154762Snate@binkert.org def getValue(self): 15164762Snate@binkert.org return long(self.value) 15174762Snate@binkert.org 151810458Sandreas.hansson@arm.com @classmethod 151910458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 152010458Sandreas.hansson@arm.com code('#include <sstream>') 152110458Sandreas.hansson@arm.com 152210458Sandreas.hansson@arm.com # Ticks are expressed in seconds in JSON files and in plain 152310458Sandreas.hansson@arm.com # Ticks in .ini files. Switch based on a config flag 152410458Sandreas.hansson@arm.com @classmethod 152510458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 152610458Sandreas.hansson@arm.com code('${ret} to_number(${src}, ${dest});') 152710458Sandreas.hansson@arm.com 15284167Sbinkertn@umich.educlass Latency(TickParamValue): 152910267SGeoffrey.Blake@arm.com ex_str = "100ns" 153010267SGeoffrey.Blake@arm.com 15313101Sstever@eecs.umich.edu def __init__(self, value): 15324167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 15334167Sbinkertn@umich.edu self.ticks = value.ticks 15344167Sbinkertn@umich.edu self.value = value.value 15354167Sbinkertn@umich.edu elif isinstance(value, Frequency): 15364167Sbinkertn@umich.edu self.ticks = value.ticks 15374167Sbinkertn@umich.edu self.value = 1.0 / value.value 15384167Sbinkertn@umich.edu elif value.endswith('t'): 15394167Sbinkertn@umich.edu self.ticks = True 15404167Sbinkertn@umich.edu self.value = int(value[:-1]) 15414167Sbinkertn@umich.edu else: 15424167Sbinkertn@umich.edu self.ticks = False 15434167Sbinkertn@umich.edu self.value = convert.toLatency(value) 15443101Sstever@eecs.umich.edu 154510267SGeoffrey.Blake@arm.com def __call__(self, value): 154610267SGeoffrey.Blake@arm.com self.__init__(value) 154710267SGeoffrey.Blake@arm.com return value 154810267SGeoffrey.Blake@arm.com 15493101Sstever@eecs.umich.edu def __getattr__(self, attr): 15503101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 15513101Sstever@eecs.umich.edu return self 15523101Sstever@eecs.umich.edu if attr == 'frequency': 15533101Sstever@eecs.umich.edu return Frequency(self) 155413663Sandreas.sandberg@arm.com raise AttributeError("Latency object has no attribute '%s'" % attr) 15553101Sstever@eecs.umich.edu 15564762Snate@binkert.org def getValue(self): 15574762Snate@binkert.org if self.ticks or self.value == 0: 15584762Snate@binkert.org value = self.value 15594762Snate@binkert.org else: 15604762Snate@binkert.org value = ticks.fromSeconds(self.value) 15614762Snate@binkert.org return long(value) 15624762Snate@binkert.org 156310380SAndrew.Bardsley@arm.com def config_value(self): 156410380SAndrew.Bardsley@arm.com return self.getValue() 156510380SAndrew.Bardsley@arm.com 15663101Sstever@eecs.umich.edu # convert latency to ticks 15673101Sstever@eecs.umich.edu def ini_str(self): 15684762Snate@binkert.org return '%d' % self.getValue() 15693101Sstever@eecs.umich.edu 15704167Sbinkertn@umich.educlass Frequency(TickParamValue): 157110267SGeoffrey.Blake@arm.com ex_str = "1GHz" 157210267SGeoffrey.Blake@arm.com 15733101Sstever@eecs.umich.edu def __init__(self, value): 15744167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 15754167Sbinkertn@umich.edu if value.value == 0: 15764167Sbinkertn@umich.edu self.value = 0 15774167Sbinkertn@umich.edu else: 15784167Sbinkertn@umich.edu self.value = 1.0 / value.value 15794167Sbinkertn@umich.edu self.ticks = value.ticks 15804167Sbinkertn@umich.edu elif isinstance(value, Frequency): 15814167Sbinkertn@umich.edu self.value = value.value 15824167Sbinkertn@umich.edu self.ticks = value.ticks 15834167Sbinkertn@umich.edu else: 15844167Sbinkertn@umich.edu self.ticks = False 15854167Sbinkertn@umich.edu self.value = convert.toFrequency(value) 15863101Sstever@eecs.umich.edu 158710267SGeoffrey.Blake@arm.com def __call__(self, value): 158810267SGeoffrey.Blake@arm.com self.__init__(value) 158910267SGeoffrey.Blake@arm.com return value 159010267SGeoffrey.Blake@arm.com 15913101Sstever@eecs.umich.edu def __getattr__(self, attr): 15923101Sstever@eecs.umich.edu if attr == 'frequency': 15933101Sstever@eecs.umich.edu return self 15943101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 15953101Sstever@eecs.umich.edu return Latency(self) 159613663Sandreas.sandberg@arm.com raise AttributeError("Frequency object has no attribute '%s'" % attr) 15973101Sstever@eecs.umich.edu 15984167Sbinkertn@umich.edu # convert latency to ticks 15994762Snate@binkert.org def getValue(self): 16004762Snate@binkert.org if self.ticks or self.value == 0: 16014762Snate@binkert.org value = self.value 16024762Snate@binkert.org else: 16034762Snate@binkert.org value = ticks.fromSeconds(1.0 / self.value) 16044762Snate@binkert.org return long(value) 16054762Snate@binkert.org 160610380SAndrew.Bardsley@arm.com def config_value(self): 160710380SAndrew.Bardsley@arm.com return self.getValue() 160810380SAndrew.Bardsley@arm.com 16093101Sstever@eecs.umich.edu def ini_str(self): 16104762Snate@binkert.org return '%d' % self.getValue() 16113101Sstever@eecs.umich.edu 161210019Sandreas.hansson@arm.com# A generic Frequency and/or Latency value. Value is stored as a 161310019Sandreas.hansson@arm.com# latency, just like Latency and Frequency. 161410019Sandreas.hansson@arm.comclass Clock(TickParamValue): 16153101Sstever@eecs.umich.edu def __init__(self, value): 16164167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 16174167Sbinkertn@umich.edu self.ticks = value.ticks 16184167Sbinkertn@umich.edu self.value = value.value 16194167Sbinkertn@umich.edu elif isinstance(value, Frequency): 16204167Sbinkertn@umich.edu self.ticks = value.ticks 16214167Sbinkertn@umich.edu self.value = 1.0 / value.value 16224167Sbinkertn@umich.edu elif value.endswith('t'): 16234167Sbinkertn@umich.edu self.ticks = True 16244167Sbinkertn@umich.edu self.value = int(value[:-1]) 16254167Sbinkertn@umich.edu else: 16264167Sbinkertn@umich.edu self.ticks = False 16274167Sbinkertn@umich.edu self.value = convert.anyToLatency(value) 16283101Sstever@eecs.umich.edu 162910267SGeoffrey.Blake@arm.com def __call__(self, value): 163010267SGeoffrey.Blake@arm.com self.__init__(value) 163110267SGeoffrey.Blake@arm.com return value 163210267SGeoffrey.Blake@arm.com 163310267SGeoffrey.Blake@arm.com def __str__(self): 163410267SGeoffrey.Blake@arm.com return "%s" % Latency(self) 163510267SGeoffrey.Blake@arm.com 16363101Sstever@eecs.umich.edu def __getattr__(self, attr): 16373101Sstever@eecs.umich.edu if attr == 'frequency': 16383101Sstever@eecs.umich.edu return Frequency(self) 16393101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 16403101Sstever@eecs.umich.edu return Latency(self) 164113663Sandreas.sandberg@arm.com raise AttributeError("Frequency object has no attribute '%s'" % attr) 16423101Sstever@eecs.umich.edu 16434762Snate@binkert.org def getValue(self): 16444762Snate@binkert.org return self.period.getValue() 16454762Snate@binkert.org 164610380SAndrew.Bardsley@arm.com def config_value(self): 164710380SAndrew.Bardsley@arm.com return self.period.config_value() 164810380SAndrew.Bardsley@arm.com 16493101Sstever@eecs.umich.edu def ini_str(self): 16503101Sstever@eecs.umich.edu return self.period.ini_str() 16513101Sstever@eecs.umich.edu 165212250Sgabeblack@google.comclass Voltage(Float): 165310267SGeoffrey.Blake@arm.com ex_str = "1V" 165410267SGeoffrey.Blake@arm.com 16559827Sakash.bagdia@arm.com def __new__(cls, value): 165612250Sgabeblack@google.com value = convert.toVoltage(value) 165712250Sgabeblack@google.com return super(cls, Voltage).__new__(cls, value) 16589827Sakash.bagdia@arm.com 165912250Sgabeblack@google.com def __init__(self, value): 166012250Sgabeblack@google.com value = convert.toVoltage(value) 166112250Sgabeblack@google.com super(Voltage, self).__init__(value) 166210267SGeoffrey.Blake@arm.com 166312250Sgabeblack@google.comclass Current(Float): 166410427Sandreas.hansson@arm.com ex_str = "1mA" 166510427Sandreas.hansson@arm.com 166610427Sandreas.hansson@arm.com def __new__(cls, value): 166712250Sgabeblack@google.com value = convert.toCurrent(value) 166812250Sgabeblack@google.com return super(cls, Current).__new__(cls, value) 166910427Sandreas.hansson@arm.com 167012250Sgabeblack@google.com def __init__(self, value): 167112250Sgabeblack@google.com value = convert.toCurrent(value) 167212250Sgabeblack@google.com super(Current, self).__init__(value) 167310458Sandreas.hansson@arm.com 167412253Sgabeblack@google.comclass Energy(Float): 167512253Sgabeblack@google.com ex_str = "1pJ" 167612253Sgabeblack@google.com 167712253Sgabeblack@google.com def __new__(cls, value): 167812253Sgabeblack@google.com value = convert.toEnergy(value) 167912253Sgabeblack@google.com return super(cls, Energy).__new__(cls, value) 168012253Sgabeblack@google.com 168112253Sgabeblack@google.com def __init__(self, value): 168212253Sgabeblack@google.com value = convert.toEnergy(value) 168312253Sgabeblack@google.com super(Energy, self).__init__(value) 168412253Sgabeblack@google.com 16853101Sstever@eecs.umich.educlass NetworkBandwidth(float,ParamValue): 16863101Sstever@eecs.umich.edu cxx_type = 'float' 168710267SGeoffrey.Blake@arm.com ex_str = "1Gbps" 168810267SGeoffrey.Blake@arm.com cmd_line_settable = True 168910267SGeoffrey.Blake@arm.com 16903101Sstever@eecs.umich.edu def __new__(cls, value): 16914167Sbinkertn@umich.edu # convert to bits per second 16924167Sbinkertn@umich.edu val = convert.toNetworkBandwidth(value) 16933101Sstever@eecs.umich.edu return super(cls, NetworkBandwidth).__new__(cls, val) 16943101Sstever@eecs.umich.edu 16953101Sstever@eecs.umich.edu def __str__(self): 16963101Sstever@eecs.umich.edu return str(self.val) 16973101Sstever@eecs.umich.edu 169810267SGeoffrey.Blake@arm.com def __call__(self, value): 169910267SGeoffrey.Blake@arm.com val = convert.toNetworkBandwidth(value) 170010267SGeoffrey.Blake@arm.com self.__init__(val) 170110267SGeoffrey.Blake@arm.com return value 170210267SGeoffrey.Blake@arm.com 17034762Snate@binkert.org def getValue(self): 17044167Sbinkertn@umich.edu # convert to seconds per byte 17054167Sbinkertn@umich.edu value = 8.0 / float(self) 17064167Sbinkertn@umich.edu # convert to ticks per byte 17074762Snate@binkert.org value = ticks.fromSeconds(value) 17084762Snate@binkert.org return float(value) 17094762Snate@binkert.org 17104762Snate@binkert.org def ini_str(self): 17114762Snate@binkert.org return '%f' % self.getValue() 17123101Sstever@eecs.umich.edu 171310380SAndrew.Bardsley@arm.com def config_value(self): 171410380SAndrew.Bardsley@arm.com return '%f' % self.getValue() 171510380SAndrew.Bardsley@arm.com 171610458Sandreas.hansson@arm.com @classmethod 171710458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 171810458Sandreas.hansson@arm.com code('#include <sstream>') 171910458Sandreas.hansson@arm.com 172010458Sandreas.hansson@arm.com @classmethod 172110458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 172210458Sandreas.hansson@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 172310458Sandreas.hansson@arm.com 17243101Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue): 17253101Sstever@eecs.umich.edu cxx_type = 'float' 172610267SGeoffrey.Blake@arm.com ex_str = "1GB/s" 172710267SGeoffrey.Blake@arm.com cmd_line_settable = True 172810267SGeoffrey.Blake@arm.com 17295469Snate@binkert.org def __new__(cls, value): 17307743Sgblack@eecs.umich.edu # convert to bytes per second 17313102Sstever@eecs.umich.edu val = convert.toMemoryBandwidth(value) 17323101Sstever@eecs.umich.edu return super(cls, MemoryBandwidth).__new__(cls, val) 17333101Sstever@eecs.umich.edu 173410267SGeoffrey.Blake@arm.com def __call__(self, value): 173510267SGeoffrey.Blake@arm.com val = convert.toMemoryBandwidth(value) 173610267SGeoffrey.Blake@arm.com self.__init__(val) 173710267SGeoffrey.Blake@arm.com return value 17383101Sstever@eecs.umich.edu 17394762Snate@binkert.org def getValue(self): 17404167Sbinkertn@umich.edu # convert to seconds per byte 17415468Snate@binkert.org value = float(self) 17425468Snate@binkert.org if value: 17435468Snate@binkert.org value = 1.0 / float(self) 17444167Sbinkertn@umich.edu # convert to ticks per byte 17454762Snate@binkert.org value = ticks.fromSeconds(value) 17464762Snate@binkert.org return float(value) 17474762Snate@binkert.org 17484762Snate@binkert.org def ini_str(self): 17494762Snate@binkert.org return '%f' % self.getValue() 17503101Sstever@eecs.umich.edu 175110380SAndrew.Bardsley@arm.com def config_value(self): 175210380SAndrew.Bardsley@arm.com return '%f' % self.getValue() 175310380SAndrew.Bardsley@arm.com 175410458Sandreas.hansson@arm.com @classmethod 175510458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 175610458Sandreas.hansson@arm.com code('#include <sstream>') 175710458Sandreas.hansson@arm.com 175810458Sandreas.hansson@arm.com @classmethod 175910458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 176010458Sandreas.hansson@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 176110458Sandreas.hansson@arm.com 17623101Sstever@eecs.umich.edu# 17633101Sstever@eecs.umich.edu# "Constants"... handy aliases for various values. 17643101Sstever@eecs.umich.edu# 17653101Sstever@eecs.umich.edu 17663102Sstever@eecs.umich.edu# Special class for NULL pointers. Note the special check in 17673102Sstever@eecs.umich.edu# make_param_value() above that lets these be assigned where a 17683102Sstever@eecs.umich.edu# SimObject is required. 17693102Sstever@eecs.umich.edu# only one copy of a particular node 17703102Sstever@eecs.umich.educlass NullSimObject(object): 17713102Sstever@eecs.umich.edu __metaclass__ = Singleton 177212197Sgabeblack@google.com _name = 'Null' 17733102Sstever@eecs.umich.edu 17743102Sstever@eecs.umich.edu def __call__(cls): 17753102Sstever@eecs.umich.edu return cls 17763102Sstever@eecs.umich.edu 17773102Sstever@eecs.umich.edu def _instantiate(self, parent = None, path = ''): 17783102Sstever@eecs.umich.edu pass 17793102Sstever@eecs.umich.edu 17803102Sstever@eecs.umich.edu def ini_str(self): 17813102Sstever@eecs.umich.edu return 'Null' 17823102Sstever@eecs.umich.edu 17833102Sstever@eecs.umich.edu def unproxy(self, base): 17843102Sstever@eecs.umich.edu return self 17853102Sstever@eecs.umich.edu 17863102Sstever@eecs.umich.edu def set_path(self, parent, name): 17873102Sstever@eecs.umich.edu pass 17884762Snate@binkert.org 178912192Sgabeblack@google.com def set_parent(self, parent, name): 179012192Sgabeblack@google.com pass 179112192Sgabeblack@google.com 179212195Sgabeblack@google.com def clear_parent(self, old_parent): 179312195Sgabeblack@google.com pass 179412195Sgabeblack@google.com 179512196Sgabeblack@google.com def descendants(self): 179612196Sgabeblack@google.com return 179712196Sgabeblack@google.com yield None 179812196Sgabeblack@google.com 179912200Sgabeblack@google.com def get_config_as_dict(self): 180012200Sgabeblack@google.com return {} 180112200Sgabeblack@google.com 18023102Sstever@eecs.umich.edu def __str__(self): 180312197Sgabeblack@google.com return self._name 18043102Sstever@eecs.umich.edu 180510380SAndrew.Bardsley@arm.com def config_value(self): 180610380SAndrew.Bardsley@arm.com return None 180710380SAndrew.Bardsley@arm.com 18084762Snate@binkert.org def getValue(self): 18094762Snate@binkert.org return None 18104762Snate@binkert.org 18113102Sstever@eecs.umich.edu# The only instance you'll ever need... 18123102Sstever@eecs.umich.eduNULL = NullSimObject() 18133102Sstever@eecs.umich.edu 18143102Sstever@eecs.umich.edudef isNullPointer(value): 18153102Sstever@eecs.umich.edu return isinstance(value, NullSimObject) 18163102Sstever@eecs.umich.edu 18173101Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound. 18183101Sstever@eecs.umich.eduMaxAddr = Addr.max 18193101Sstever@eecs.umich.eduMaxTick = Tick.max 18203101Sstever@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr) 18213101Sstever@eecs.umich.edu 18223101Sstever@eecs.umich.edu 18233101Sstever@eecs.umich.edu##################################################################### 18243101Sstever@eecs.umich.edu# 18253101Sstever@eecs.umich.edu# Port objects 18263101Sstever@eecs.umich.edu# 18273101Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system. 18283101Sstever@eecs.umich.edu# 18293101Sstever@eecs.umich.edu##################################################################### 18303101Sstever@eecs.umich.edu 18313101Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a 18323101Sstever@eecs.umich.edu# particular SimObject. 18333101Sstever@eecs.umich.educlass PortRef(object): 18348839Sandreas.hansson@arm.com def __init__(self, simobj, name, role): 18353105Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 18363101Sstever@eecs.umich.edu self.simobj = simobj 18373101Sstever@eecs.umich.edu self.name = name 18388839Sandreas.hansson@arm.com self.role = role 18393101Sstever@eecs.umich.edu self.peer = None # not associated with another port yet 18403101Sstever@eecs.umich.edu self.ccConnected = False # C++ port connection done? 18413105Sstever@eecs.umich.edu self.index = -1 # always -1 for non-vector ports 18423101Sstever@eecs.umich.edu 18433103Sstever@eecs.umich.edu def __str__(self): 18443105Sstever@eecs.umich.edu return '%s.%s' % (self.simobj, self.name) 18453103Sstever@eecs.umich.edu 18468840Sandreas.hansson@arm.com def __len__(self): 18478840Sandreas.hansson@arm.com # Return the number of connected ports, i.e. 0 is we have no 18488840Sandreas.hansson@arm.com # peer and 1 if we do. 18498840Sandreas.hansson@arm.com return int(self.peer != None) 18508840Sandreas.hansson@arm.com 18513105Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 18523105Sstever@eecs.umich.edu def ini_str(self): 18533105Sstever@eecs.umich.edu return str(self.peer) 18543105Sstever@eecs.umich.edu 18559017Sandreas.hansson@arm.com # for config.json 18569017Sandreas.hansson@arm.com def get_config_as_dict(self): 18579017Sandreas.hansson@arm.com return {'role' : self.role, 'peer' : str(self.peer)} 18589017Sandreas.hansson@arm.com 18593105Sstever@eecs.umich.edu def __getattr__(self, attr): 18603105Sstever@eecs.umich.edu if attr == 'peerObj': 18613105Sstever@eecs.umich.edu # shorthand for proxies 18623105Sstever@eecs.umich.edu return self.peer.simobj 186313663Sandreas.sandberg@arm.com raise AttributeError("'%s' object has no attribute '%s'" % \ 186413663Sandreas.sandberg@arm.com (self.__class__.__name__, attr)) 18653105Sstever@eecs.umich.edu 18663105Sstever@eecs.umich.edu # Full connection is symmetric (both ways). Called via 18673105Sstever@eecs.umich.edu # SimObject.__setattr__ as a result of a port assignment, e.g., 18683109Sstever@eecs.umich.edu # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 18693105Sstever@eecs.umich.edu # e.g., "obj1.portA[3] = obj2.portB". 18703105Sstever@eecs.umich.edu def connect(self, other): 18713105Sstever@eecs.umich.edu if isinstance(other, VectorPortRef): 18723105Sstever@eecs.umich.edu # reference to plain VectorPort is implicit append 18733105Sstever@eecs.umich.edu other = other._get_next() 18743105Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 18759014Sandreas.hansson@arm.com fatal("Port %s is already connected to %s, cannot connect %s\n", 18769014Sandreas.hansson@arm.com self, self.peer, other); 18773101Sstever@eecs.umich.edu self.peer = other 18783109Sstever@eecs.umich.edu if proxy.isproxy(other): 18793109Sstever@eecs.umich.edu other.set_param_desc(PortParamDesc()) 18803109Sstever@eecs.umich.edu elif isinstance(other, PortRef): 18813109Sstever@eecs.umich.edu if other.peer is not self: 18823109Sstever@eecs.umich.edu other.connect(self) 18833109Sstever@eecs.umich.edu else: 188413663Sandreas.sandberg@arm.com raise TypeError("assigning non-port reference '%s' to port '%s'" \ 188513663Sandreas.sandberg@arm.com % (other, self)) 18863101Sstever@eecs.umich.edu 188710355SGeoffrey.Blake@arm.com # Allow a master/slave port pair to be spliced between 188810355SGeoffrey.Blake@arm.com # a port and its connected peer. Useful operation for connecting 188910355SGeoffrey.Blake@arm.com # instrumentation structures into a system when it is necessary 189010355SGeoffrey.Blake@arm.com # to connect the instrumentation after the full system has been 189110355SGeoffrey.Blake@arm.com # constructed. 189210355SGeoffrey.Blake@arm.com def splice(self, new_master_peer, new_slave_peer): 189313543Sgabeblack@google.com if not self.peer or proxy.isproxy(self.peer): 189413543Sgabeblack@google.com fatal("Port %s not connected, cannot splice in new peers\n", self) 189513543Sgabeblack@google.com 189613543Sgabeblack@google.com if not isinstance(new_master_peer, PortRef) or \ 189713543Sgabeblack@google.com not isinstance(new_slave_peer, PortRef): 189813663Sandreas.sandberg@arm.com raise TypeError( 189913543Sgabeblack@google.com "Splicing non-port references '%s','%s' to port '%s'" % \ 190013663Sandreas.sandberg@arm.com (new_master_peer, new_slave_peer, self)) 190113543Sgabeblack@google.com 190213543Sgabeblack@google.com old_peer = self.peer 190313543Sgabeblack@google.com if self.role == 'SLAVE': 190413543Sgabeblack@google.com self.peer = new_master_peer 190513543Sgabeblack@google.com old_peer.peer = new_slave_peer 190613543Sgabeblack@google.com new_master_peer.connect(self) 190713543Sgabeblack@google.com new_slave_peer.connect(old_peer) 190813543Sgabeblack@google.com elif self.role == 'MASTER': 190913543Sgabeblack@google.com self.peer = new_slave_peer 191013543Sgabeblack@google.com old_peer.peer = new_master_peer 191113543Sgabeblack@google.com new_slave_peer.connect(self) 191213543Sgabeblack@google.com new_master_peer.connect(old_peer) 191310355SGeoffrey.Blake@arm.com else: 191413543Sgabeblack@google.com panic("Port %s has unknown role, "+\ 191513543Sgabeblack@google.com "cannot splice in new peers\n", self) 191610355SGeoffrey.Blake@arm.com 19173105Sstever@eecs.umich.edu def clone(self, simobj, memo): 191813675Sandreas.sandberg@arm.com if self in memo: 19193105Sstever@eecs.umich.edu return memo[self] 19203101Sstever@eecs.umich.edu newRef = copy.copy(self) 19213105Sstever@eecs.umich.edu memo[self] = newRef 19223105Sstever@eecs.umich.edu newRef.simobj = simobj 19233101Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 19243105Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 19253179Sstever@eecs.umich.edu peerObj = self.peer.simobj(_memo=memo) 19263105Sstever@eecs.umich.edu newRef.peer = self.peer.clone(peerObj, memo) 19273105Sstever@eecs.umich.edu assert(not isinstance(newRef.peer, VectorPortRef)) 19283101Sstever@eecs.umich.edu return newRef 19293101Sstever@eecs.umich.edu 19303105Sstever@eecs.umich.edu def unproxy(self, simobj): 19313105Sstever@eecs.umich.edu assert(simobj is self.simobj) 19323105Sstever@eecs.umich.edu if proxy.isproxy(self.peer): 19333105Sstever@eecs.umich.edu try: 19343105Sstever@eecs.umich.edu realPeer = self.peer.unproxy(self.simobj) 19353105Sstever@eecs.umich.edu except: 193612563Sgabeblack@google.com print("Error in unproxying port '%s' of %s" % 193712563Sgabeblack@google.com (self.name, self.simobj.path())) 19383105Sstever@eecs.umich.edu raise 19393105Sstever@eecs.umich.edu self.connect(realPeer) 19403105Sstever@eecs.umich.edu 19413101Sstever@eecs.umich.edu # Call C++ to create corresponding port connection between C++ objects 19423101Sstever@eecs.umich.edu def ccConnect(self): 194311802Sandreas.sandberg@arm.com from _m5.pyobject import connectPorts 19444762Snate@binkert.org 194513594Snicholas.lindsay@arm.com if self.ccConnected: # already done this 19468839Sandreas.hansson@arm.com return 19478839Sandreas.hansson@arm.com 19483101Sstever@eecs.umich.edu peer = self.peer 19495578SSteve.Reinhardt@amd.com if not self.peer: # nothing to connect to 19505578SSteve.Reinhardt@amd.com return 19518839Sandreas.hansson@arm.com 19528839Sandreas.hansson@arm.com # check that we connect a master to a slave 19538839Sandreas.hansson@arm.com if self.role == peer.role: 195413663Sandreas.sandberg@arm.com raise TypeError( 195513663Sandreas.sandberg@arm.com "cannot connect '%s' and '%s' due to identical role '%s'" % \ 195613663Sandreas.sandberg@arm.com (peer, self, self.role)) 19578839Sandreas.hansson@arm.com 195813594Snicholas.lindsay@arm.com if self.role == 'SLAVE': 195913594Snicholas.lindsay@arm.com # do nothing and let the master take care of it 196013594Snicholas.lindsay@arm.com return 196113594Snicholas.lindsay@arm.com 19627526Ssteve.reinhardt@amd.com try: 19638839Sandreas.hansson@arm.com # self is always the master and peer the slave 19647526Ssteve.reinhardt@amd.com connectPorts(self.simobj.getCCObject(), self.name, self.index, 19657526Ssteve.reinhardt@amd.com peer.simobj.getCCObject(), peer.name, peer.index) 19667526Ssteve.reinhardt@amd.com except: 196712563Sgabeblack@google.com print("Error connecting port %s.%s to %s.%s" % 19687526Ssteve.reinhardt@amd.com (self.simobj.path(), self.name, 196912563Sgabeblack@google.com peer.simobj.path(), peer.name)) 19707526Ssteve.reinhardt@amd.com raise 19713101Sstever@eecs.umich.edu self.ccConnected = True 19723101Sstever@eecs.umich.edu peer.ccConnected = True 19733101Sstever@eecs.umich.edu 19743105Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a 19753105Sstever@eecs.umich.edu# PortRef, but has an index. 19763105Sstever@eecs.umich.educlass VectorPortElementRef(PortRef): 19778839Sandreas.hansson@arm.com def __init__(self, simobj, name, role, index): 19788839Sandreas.hansson@arm.com PortRef.__init__(self, simobj, name, role) 19793105Sstever@eecs.umich.edu self.index = index 19803105Sstever@eecs.umich.edu 19813105Sstever@eecs.umich.edu def __str__(self): 19823105Sstever@eecs.umich.edu return '%s.%s[%d]' % (self.simobj, self.name, self.index) 19833105Sstever@eecs.umich.edu 19843105Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element). 19853105Sstever@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances. 19863105Sstever@eecs.umich.educlass VectorPortRef(object): 19878839Sandreas.hansson@arm.com def __init__(self, simobj, name, role): 19883105Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 19893105Sstever@eecs.umich.edu self.simobj = simobj 19903105Sstever@eecs.umich.edu self.name = name 19918839Sandreas.hansson@arm.com self.role = role 19923105Sstever@eecs.umich.edu self.elements = [] 19933105Sstever@eecs.umich.edu 19943109Sstever@eecs.umich.edu def __str__(self): 19953109Sstever@eecs.umich.edu return '%s.%s[:]' % (self.simobj, self.name) 19963109Sstever@eecs.umich.edu 19978840Sandreas.hansson@arm.com def __len__(self): 19988840Sandreas.hansson@arm.com # Return the number of connected peers, corresponding the the 19998840Sandreas.hansson@arm.com # length of the elements. 20008840Sandreas.hansson@arm.com return len(self.elements) 20018840Sandreas.hansson@arm.com 20023105Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 20033105Sstever@eecs.umich.edu def ini_str(self): 20043105Sstever@eecs.umich.edu return ' '.join([el.ini_str() for el in self.elements]) 20053105Sstever@eecs.umich.edu 20069017Sandreas.hansson@arm.com # for config.json 20079017Sandreas.hansson@arm.com def get_config_as_dict(self): 20089017Sandreas.hansson@arm.com return {'role' : self.role, 20099017Sandreas.hansson@arm.com 'peer' : [el.ini_str() for el in self.elements]} 20109017Sandreas.hansson@arm.com 20113105Sstever@eecs.umich.edu def __getitem__(self, key): 20123105Sstever@eecs.umich.edu if not isinstance(key, int): 201313663Sandreas.sandberg@arm.com raise TypeError("VectorPort index must be integer") 20143105Sstever@eecs.umich.edu if key >= len(self.elements): 20153105Sstever@eecs.umich.edu # need to extend list 20168839Sandreas.hansson@arm.com ext = [VectorPortElementRef(self.simobj, self.name, self.role, i) 20173105Sstever@eecs.umich.edu for i in range(len(self.elements), key+1)] 20183105Sstever@eecs.umich.edu self.elements.extend(ext) 20193105Sstever@eecs.umich.edu return self.elements[key] 20203105Sstever@eecs.umich.edu 20213105Sstever@eecs.umich.edu def _get_next(self): 20223105Sstever@eecs.umich.edu return self[len(self.elements)] 20233105Sstever@eecs.umich.edu 20243105Sstever@eecs.umich.edu def __setitem__(self, key, value): 20253105Sstever@eecs.umich.edu if not isinstance(key, int): 202613663Sandreas.sandberg@arm.com raise TypeError("VectorPort index must be integer") 20273105Sstever@eecs.umich.edu self[key].connect(value) 20283105Sstever@eecs.umich.edu 20293105Sstever@eecs.umich.edu def connect(self, other): 20303109Sstever@eecs.umich.edu if isinstance(other, (list, tuple)): 20313109Sstever@eecs.umich.edu # Assign list of port refs to vector port. 20323109Sstever@eecs.umich.edu # For now, append them... not sure if that's the right semantics 20333109Sstever@eecs.umich.edu # or if it should replace the current vector. 20343109Sstever@eecs.umich.edu for ref in other: 20353109Sstever@eecs.umich.edu self._get_next().connect(ref) 20363109Sstever@eecs.umich.edu else: 20373109Sstever@eecs.umich.edu # scalar assignment to plain VectorPort is implicit append 20383109Sstever@eecs.umich.edu self._get_next().connect(other) 20393109Sstever@eecs.umich.edu 20403109Sstever@eecs.umich.edu def clone(self, simobj, memo): 204113675Sandreas.sandberg@arm.com if self in memo: 20423109Sstever@eecs.umich.edu return memo[self] 20433109Sstever@eecs.umich.edu newRef = copy.copy(self) 20443109Sstever@eecs.umich.edu memo[self] = newRef 20453109Sstever@eecs.umich.edu newRef.simobj = simobj 20463109Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 20473109Sstever@eecs.umich.edu newRef.elements = [el.clone(simobj, memo) for el in self.elements] 20483109Sstever@eecs.umich.edu return newRef 20493105Sstever@eecs.umich.edu 20503105Sstever@eecs.umich.edu def unproxy(self, simobj): 20513105Sstever@eecs.umich.edu [el.unproxy(simobj) for el in self.elements] 20523105Sstever@eecs.umich.edu 20533105Sstever@eecs.umich.edu def ccConnect(self): 20543105Sstever@eecs.umich.edu [el.ccConnect() for el in self.elements] 20553105Sstever@eecs.umich.edu 20563101Sstever@eecs.umich.edu# Port description object. Like a ParamDesc object, this represents a 20573101Sstever@eecs.umich.edu# logical port in the SimObject class, not a particular port on a 20583101Sstever@eecs.umich.edu# SimObject instance. The latter are represented by PortRef objects. 20593101Sstever@eecs.umich.educlass Port(object): 20603101Sstever@eecs.umich.edu # Generate a PortRef for this port on the given SimObject with the 20613101Sstever@eecs.umich.edu # given name 20623105Sstever@eecs.umich.edu def makeRef(self, simobj): 20638839Sandreas.hansson@arm.com return PortRef(simobj, self.name, self.role) 20643101Sstever@eecs.umich.edu 20653101Sstever@eecs.umich.edu # Connect an instance of this port (on the given SimObject with 20663101Sstever@eecs.umich.edu # the given name) with the port described by the supplied PortRef 20673105Sstever@eecs.umich.edu def connect(self, simobj, ref): 20683105Sstever@eecs.umich.edu self.makeRef(simobj).connect(ref) 20693101Sstever@eecs.umich.edu 20708840Sandreas.hansson@arm.com # No need for any pre-declarations at the moment as we merely rely 20718840Sandreas.hansson@arm.com # on an unsigned int. 20728840Sandreas.hansson@arm.com def cxx_predecls(self, code): 20738840Sandreas.hansson@arm.com pass 20748840Sandreas.hansson@arm.com 207511988Sandreas.sandberg@arm.com def pybind_predecls(self, code): 207611988Sandreas.sandberg@arm.com cls.cxx_predecls(self, code) 207711988Sandreas.sandberg@arm.com 20788840Sandreas.hansson@arm.com # Declare an unsigned int with the same name as the port, that 20798840Sandreas.hansson@arm.com # will eventually hold the number of connected ports (and thus the 20808840Sandreas.hansson@arm.com # number of elements for a VectorPort). 20818840Sandreas.hansson@arm.com def cxx_decl(self, code): 20828840Sandreas.hansson@arm.com code('unsigned int port_${{self.name}}_connection_count;') 20838840Sandreas.hansson@arm.com 20848839Sandreas.hansson@arm.comclass MasterPort(Port): 20858839Sandreas.hansson@arm.com # MasterPort("description") 20868839Sandreas.hansson@arm.com def __init__(self, *args): 20878839Sandreas.hansson@arm.com if len(args) == 1: 20888839Sandreas.hansson@arm.com self.desc = args[0] 20898839Sandreas.hansson@arm.com self.role = 'MASTER' 20908839Sandreas.hansson@arm.com else: 209113663Sandreas.sandberg@arm.com raise TypeError('wrong number of arguments') 20928839Sandreas.hansson@arm.com 20938839Sandreas.hansson@arm.comclass SlavePort(Port): 20948839Sandreas.hansson@arm.com # SlavePort("description") 20958839Sandreas.hansson@arm.com def __init__(self, *args): 20968839Sandreas.hansson@arm.com if len(args) == 1: 20978839Sandreas.hansson@arm.com self.desc = args[0] 20988839Sandreas.hansson@arm.com self.role = 'SLAVE' 20998839Sandreas.hansson@arm.com else: 210013663Sandreas.sandberg@arm.com raise TypeError('wrong number of arguments') 21018839Sandreas.hansson@arm.com 21023101Sstever@eecs.umich.edu# VectorPort description object. Like Port, but represents a vector 210310405Sandreas.hansson@arm.com# of connections (e.g., as on a XBar). 21043101Sstever@eecs.umich.educlass VectorPort(Port): 21053105Sstever@eecs.umich.edu def __init__(self, *args): 21063101Sstever@eecs.umich.edu self.isVec = True 21073101Sstever@eecs.umich.edu 21083105Sstever@eecs.umich.edu def makeRef(self, simobj): 21098839Sandreas.hansson@arm.com return VectorPortRef(simobj, self.name, self.role) 21108839Sandreas.hansson@arm.com 21118839Sandreas.hansson@arm.comclass VectorMasterPort(VectorPort): 21128839Sandreas.hansson@arm.com # VectorMasterPort("description") 21138839Sandreas.hansson@arm.com def __init__(self, *args): 21148839Sandreas.hansson@arm.com if len(args) == 1: 21158839Sandreas.hansson@arm.com self.desc = args[0] 21168839Sandreas.hansson@arm.com self.role = 'MASTER' 21178839Sandreas.hansson@arm.com VectorPort.__init__(self, *args) 21188839Sandreas.hansson@arm.com else: 211913663Sandreas.sandberg@arm.com raise TypeError('wrong number of arguments') 21208839Sandreas.hansson@arm.com 21218839Sandreas.hansson@arm.comclass VectorSlavePort(VectorPort): 21228839Sandreas.hansson@arm.com # VectorSlavePort("description") 21238839Sandreas.hansson@arm.com def __init__(self, *args): 21248839Sandreas.hansson@arm.com if len(args) == 1: 21258839Sandreas.hansson@arm.com self.desc = args[0] 21268839Sandreas.hansson@arm.com self.role = 'SLAVE' 21278839Sandreas.hansson@arm.com VectorPort.__init__(self, *args) 21288839Sandreas.hansson@arm.com else: 212913663Sandreas.sandberg@arm.com raise TypeError('wrong number of arguments') 21303105Sstever@eecs.umich.edu 21313109Sstever@eecs.umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 21323109Sstever@eecs.umich.edu# proxy objects (via set_param_desc()) so that proxy error messages 21333109Sstever@eecs.umich.edu# make sense. 21343109Sstever@eecs.umich.educlass PortParamDesc(object): 21353109Sstever@eecs.umich.edu __metaclass__ = Singleton 21363109Sstever@eecs.umich.edu 21373109Sstever@eecs.umich.edu ptype_str = 'Port' 21383109Sstever@eecs.umich.edu ptype = Port 21393105Sstever@eecs.umich.edu 21406654Snate@binkert.orgbaseEnums = allEnums.copy() 21416654Snate@binkert.orgbaseParams = allParams.copy() 21426654Snate@binkert.org 21436654Snate@binkert.orgdef clear(): 21446654Snate@binkert.org global allEnums, allParams 21456654Snate@binkert.org 21466654Snate@binkert.org allEnums = baseEnums.copy() 21476654Snate@binkert.org allParams = baseParams.copy() 21486654Snate@binkert.org 21493101Sstever@eecs.umich.edu__all__ = ['Param', 'VectorParam', 215013558Snikos.nikoleris@arm.com 'Enum', 'ScopedEnum', 'Bool', 'String', 'Float', 21513101Sstever@eecs.umich.edu 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 21523101Sstever@eecs.umich.edu 'Int32', 'UInt32', 'Int64', 'UInt64', 21533101Sstever@eecs.umich.edu 'Counter', 'Addr', 'Tick', 'Percent', 21543101Sstever@eecs.umich.edu 'TcpPort', 'UdpPort', 'EthernetAddr', 21557777Sgblack@eecs.umich.edu 'IpAddress', 'IpNetmask', 'IpWithPort', 21563101Sstever@eecs.umich.edu 'MemorySize', 'MemorySize32', 215712253Sgabeblack@google.com 'Latency', 'Frequency', 'Clock', 'Voltage', 'Current', 'Energy', 21583101Sstever@eecs.umich.edu 'NetworkBandwidth', 'MemoryBandwidth', 21599232Sandreas.hansson@arm.com 'AddrRange', 21603101Sstever@eecs.umich.edu 'MaxAddr', 'MaxTick', 'AllMemory', 21613885Sbinkertn@umich.edu 'Time', 21623102Sstever@eecs.umich.edu 'NextEthernetAddr', 'NULL', 21638839Sandreas.hansson@arm.com 'MasterPort', 'SlavePort', 21648839Sandreas.hansson@arm.com 'VectorMasterPort', 'VectorSlavePort'] 2165