params.py revision 12196:4c1449b32810
111988Sandreas.sandberg@arm.com# Copyright (c) 2012-2014, 2017 ARM Limited 28839Sandreas.hansson@arm.com# All rights reserved. 38839Sandreas.hansson@arm.com# 48839Sandreas.hansson@arm.com# The license below extends only to copyright in the software and shall 58839Sandreas.hansson@arm.com# not be construed as granting a license to any other intellectual 68839Sandreas.hansson@arm.com# property including but not limited to intellectual property relating 78839Sandreas.hansson@arm.com# to a hardware implementation of the functionality of the software 88839Sandreas.hansson@arm.com# licensed hereunder. You may use the software subject to the license 98839Sandreas.hansson@arm.com# terms below provided that you ensure that this notice is replicated 108839Sandreas.hansson@arm.com# unmodified and in its entirety in all distributions of the software, 118839Sandreas.hansson@arm.com# modified or unmodified, in source code or in binary form. 128839Sandreas.hansson@arm.com# 133101Sstever@eecs.umich.edu# Copyright (c) 2004-2006 The Regents of The University of Michigan 148579Ssteve.reinhardt@amd.com# Copyright (c) 2010-2011 Advanced Micro Devices, Inc. 153101Sstever@eecs.umich.edu# All rights reserved. 163101Sstever@eecs.umich.edu# 173101Sstever@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 183101Sstever@eecs.umich.edu# modification, are permitted provided that the following conditions are 193101Sstever@eecs.umich.edu# met: redistributions of source code must retain the above copyright 203101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 213101Sstever@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 223101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 233101Sstever@eecs.umich.edu# documentation and/or other materials provided with the distribution; 243101Sstever@eecs.umich.edu# neither the name of the copyright holders nor the names of its 253101Sstever@eecs.umich.edu# contributors may be used to endorse or promote products derived from 263101Sstever@eecs.umich.edu# this software without specific prior written permission. 273101Sstever@eecs.umich.edu# 283101Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 293101Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 303101Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 313101Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 323101Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 333101Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 343101Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 353101Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 363101Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 373101Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 383101Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 393101Sstever@eecs.umich.edu# 403101Sstever@eecs.umich.edu# Authors: Steve Reinhardt 413101Sstever@eecs.umich.edu# Nathan Binkert 427778Sgblack@eecs.umich.edu# Gabe Black 438839Sandreas.hansson@arm.com# Andreas Hansson 443101Sstever@eecs.umich.edu 453101Sstever@eecs.umich.edu##################################################################### 463101Sstever@eecs.umich.edu# 473101Sstever@eecs.umich.edu# Parameter description classes 483101Sstever@eecs.umich.edu# 493101Sstever@eecs.umich.edu# The _params dictionary in each class maps parameter names to either 503101Sstever@eecs.umich.edu# a Param or a VectorParam object. These objects contain the 513101Sstever@eecs.umich.edu# parameter description string, the parameter type, and the default 523101Sstever@eecs.umich.edu# value (if any). The convert() method on these objects is used to 533101Sstever@eecs.umich.edu# force whatever value is assigned to the parameter to the appropriate 543101Sstever@eecs.umich.edu# type. 553101Sstever@eecs.umich.edu# 563101Sstever@eecs.umich.edu# Note that the default values are loaded into the class's attribute 573101Sstever@eecs.umich.edu# space when the parameter dictionary is initialized (in 583101Sstever@eecs.umich.edu# MetaSimObject._new_param()); after that point they aren't used. 593101Sstever@eecs.umich.edu# 603101Sstever@eecs.umich.edu##################################################################### 613101Sstever@eecs.umich.edu 623885Sbinkertn@umich.eduimport copy 633885Sbinkertn@umich.eduimport datetime 644762Snate@binkert.orgimport re 653885Sbinkertn@umich.eduimport sys 663885Sbinkertn@umich.eduimport time 677528Ssteve.reinhardt@amd.comimport math 683885Sbinkertn@umich.edu 694380Sbinkertn@umich.eduimport proxy 704167Sbinkertn@umich.eduimport ticks 713102Sstever@eecs.umich.edufrom util import * 723101Sstever@eecs.umich.edu 734762Snate@binkert.orgdef isSimObject(*args, **kwargs): 744762Snate@binkert.org return SimObject.isSimObject(*args, **kwargs) 754762Snate@binkert.org 764762Snate@binkert.orgdef isSimObjectSequence(*args, **kwargs): 774762Snate@binkert.org return SimObject.isSimObjectSequence(*args, **kwargs) 784762Snate@binkert.org 794762Snate@binkert.orgdef isSimObjectClass(*args, **kwargs): 804762Snate@binkert.org return SimObject.isSimObjectClass(*args, **kwargs) 814762Snate@binkert.org 825033Smilesck@eecs.umich.eduallParams = {} 835033Smilesck@eecs.umich.edu 845033Smilesck@eecs.umich.educlass MetaParamValue(type): 855033Smilesck@eecs.umich.edu def __new__(mcls, name, bases, dct): 865033Smilesck@eecs.umich.edu cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) 875033Smilesck@eecs.umich.edu assert name not in allParams 885033Smilesck@eecs.umich.edu allParams[name] = cls 895033Smilesck@eecs.umich.edu return cls 905033Smilesck@eecs.umich.edu 915033Smilesck@eecs.umich.edu 923101Sstever@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject 933101Sstever@eecs.umich.edu# parameters. 943101Sstever@eecs.umich.educlass ParamValue(object): 955033Smilesck@eecs.umich.edu __metaclass__ = MetaParamValue 9610267SGeoffrey.Blake@arm.com cmd_line_settable = False 978596Ssteve.reinhardt@amd.com 988596Ssteve.reinhardt@amd.com # Generate the code needed as a prerequisite for declaring a C++ 998596Ssteve.reinhardt@amd.com # object of this type. Typically generates one or more #include 1008596Ssteve.reinhardt@amd.com # statements. Used when declaring parameters of this type. 1017673Snate@binkert.org @classmethod 1027673Snate@binkert.org def cxx_predecls(cls, code): 1037673Snate@binkert.org pass 1047673Snate@binkert.org 10511988Sandreas.sandberg@arm.com @classmethod 10611988Sandreas.sandberg@arm.com def pybind_predecls(cls, code): 10711988Sandreas.sandberg@arm.com cls.cxx_predecls(code) 10811988Sandreas.sandberg@arm.com 1093101Sstever@eecs.umich.edu # default for printing to .ini file is regular string conversion. 1103101Sstever@eecs.umich.edu # will be overridden in some cases 1113101Sstever@eecs.umich.edu def ini_str(self): 1123101Sstever@eecs.umich.edu return str(self) 1133101Sstever@eecs.umich.edu 11410380SAndrew.Bardsley@arm.com # default for printing to .json file is regular string conversion. 11510380SAndrew.Bardsley@arm.com # will be overridden in some cases, mostly to use native Python 11610380SAndrew.Bardsley@arm.com # types where there are similar JSON types 11710380SAndrew.Bardsley@arm.com def config_value(self): 11810380SAndrew.Bardsley@arm.com return str(self) 11910380SAndrew.Bardsley@arm.com 12010458Sandreas.hansson@arm.com # Prerequisites for .ini parsing with cxx_ini_parse 12110458Sandreas.hansson@arm.com @classmethod 12210458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 12310458Sandreas.hansson@arm.com pass 12410458Sandreas.hansson@arm.com 12510458Sandreas.hansson@arm.com # parse a .ini file entry for this param from string expression 12610458Sandreas.hansson@arm.com # src into lvalue dest (of the param's C++ type) 12710458Sandreas.hansson@arm.com @classmethod 12810458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 12910458Sandreas.hansson@arm.com code('// Unhandled param type: %s' % cls.__name__) 13010458Sandreas.hansson@arm.com code('%s false;' % ret) 13110458Sandreas.hansson@arm.com 1323101Sstever@eecs.umich.edu # allows us to blithely call unproxy() on things without checking 1333101Sstever@eecs.umich.edu # if they're really proxies or not 1343101Sstever@eecs.umich.edu def unproxy(self, base): 1353101Sstever@eecs.umich.edu return self 1363101Sstever@eecs.umich.edu 13710267SGeoffrey.Blake@arm.com # Produce a human readable version of the stored value 13810267SGeoffrey.Blake@arm.com def pretty_print(self, value): 13910267SGeoffrey.Blake@arm.com return str(value) 14010267SGeoffrey.Blake@arm.com 1413101Sstever@eecs.umich.edu# Regular parameter description. 1423101Sstever@eecs.umich.educlass ParamDesc(object): 1433101Sstever@eecs.umich.edu def __init__(self, ptype_str, ptype, *args, **kwargs): 1443101Sstever@eecs.umich.edu self.ptype_str = ptype_str 1453101Sstever@eecs.umich.edu # remember ptype only if it is provided 1463101Sstever@eecs.umich.edu if ptype != None: 1473101Sstever@eecs.umich.edu self.ptype = ptype 1483101Sstever@eecs.umich.edu 1493101Sstever@eecs.umich.edu if args: 1503101Sstever@eecs.umich.edu if len(args) == 1: 1513101Sstever@eecs.umich.edu self.desc = args[0] 1523101Sstever@eecs.umich.edu elif len(args) == 2: 1533101Sstever@eecs.umich.edu self.default = args[0] 1543101Sstever@eecs.umich.edu self.desc = args[1] 1553101Sstever@eecs.umich.edu else: 1563101Sstever@eecs.umich.edu raise TypeError, 'too many arguments' 1573101Sstever@eecs.umich.edu 1583101Sstever@eecs.umich.edu if kwargs.has_key('desc'): 1593101Sstever@eecs.umich.edu assert(not hasattr(self, 'desc')) 1603101Sstever@eecs.umich.edu self.desc = kwargs['desc'] 1613101Sstever@eecs.umich.edu del kwargs['desc'] 1623101Sstever@eecs.umich.edu 1633101Sstever@eecs.umich.edu if kwargs.has_key('default'): 1643101Sstever@eecs.umich.edu assert(not hasattr(self, 'default')) 1653101Sstever@eecs.umich.edu self.default = kwargs['default'] 1663101Sstever@eecs.umich.edu del kwargs['default'] 1673101Sstever@eecs.umich.edu 1683101Sstever@eecs.umich.edu if kwargs: 1693101Sstever@eecs.umich.edu raise TypeError, 'extra unknown kwargs %s' % kwargs 1703101Sstever@eecs.umich.edu 1713101Sstever@eecs.umich.edu if not hasattr(self, 'desc'): 1723101Sstever@eecs.umich.edu raise TypeError, 'desc attribute missing' 1733101Sstever@eecs.umich.edu 1743101Sstever@eecs.umich.edu def __getattr__(self, attr): 1753101Sstever@eecs.umich.edu if attr == 'ptype': 1765033Smilesck@eecs.umich.edu ptype = SimObject.allClasses[self.ptype_str] 1776656Snate@binkert.org assert isSimObjectClass(ptype) 1785033Smilesck@eecs.umich.edu self.ptype = ptype 1795033Smilesck@eecs.umich.edu return ptype 1805033Smilesck@eecs.umich.edu 1813101Sstever@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 1823101Sstever@eecs.umich.edu (type(self).__name__, attr) 1833101Sstever@eecs.umich.edu 18410267SGeoffrey.Blake@arm.com def example_str(self): 18510267SGeoffrey.Blake@arm.com if hasattr(self.ptype, "ex_str"): 18610267SGeoffrey.Blake@arm.com return self.ptype.ex_str 18710267SGeoffrey.Blake@arm.com else: 18810267SGeoffrey.Blake@arm.com return self.ptype_str 18910267SGeoffrey.Blake@arm.com 19010267SGeoffrey.Blake@arm.com # Is the param available to be exposed on the command line 19110267SGeoffrey.Blake@arm.com def isCmdLineSettable(self): 19210267SGeoffrey.Blake@arm.com if hasattr(self.ptype, "cmd_line_settable"): 19310267SGeoffrey.Blake@arm.com return self.ptype.cmd_line_settable 19410267SGeoffrey.Blake@arm.com else: 19510267SGeoffrey.Blake@arm.com return False 19610267SGeoffrey.Blake@arm.com 1973101Sstever@eecs.umich.edu def convert(self, value): 1983101Sstever@eecs.umich.edu if isinstance(value, proxy.BaseProxy): 1993101Sstever@eecs.umich.edu value.set_param_desc(self) 2003101Sstever@eecs.umich.edu return value 2013101Sstever@eecs.umich.edu if not hasattr(self, 'ptype') and isNullPointer(value): 2023101Sstever@eecs.umich.edu # deferred evaluation of SimObject; continue to defer if 2033101Sstever@eecs.umich.edu # we're just assigning a null pointer 2043101Sstever@eecs.umich.edu return value 2053101Sstever@eecs.umich.edu if isinstance(value, self.ptype): 2063101Sstever@eecs.umich.edu return value 2073102Sstever@eecs.umich.edu if isNullPointer(value) and isSimObjectClass(self.ptype): 2083101Sstever@eecs.umich.edu return value 2093101Sstever@eecs.umich.edu return self.ptype(value) 2103101Sstever@eecs.umich.edu 21110267SGeoffrey.Blake@arm.com def pretty_print(self, value): 21210267SGeoffrey.Blake@arm.com if isinstance(value, proxy.BaseProxy): 21310267SGeoffrey.Blake@arm.com return str(value) 21410267SGeoffrey.Blake@arm.com if isNullPointer(value): 21510267SGeoffrey.Blake@arm.com return NULL 21610267SGeoffrey.Blake@arm.com return self.ptype(value).pretty_print(value) 21710267SGeoffrey.Blake@arm.com 2187673Snate@binkert.org def cxx_predecls(self, code): 2198607Sgblack@eecs.umich.edu code('#include <cstddef>') 2207673Snate@binkert.org self.ptype.cxx_predecls(code) 2213101Sstever@eecs.umich.edu 22211988Sandreas.sandberg@arm.com def pybind_predecls(self, code): 22311988Sandreas.sandberg@arm.com self.ptype.pybind_predecls(code) 22411988Sandreas.sandberg@arm.com 2257673Snate@binkert.org def cxx_decl(self, code): 2267673Snate@binkert.org code('${{self.ptype.cxx_type}} ${{self.name}};') 2273101Sstever@eecs.umich.edu 2283101Sstever@eecs.umich.edu# Vector-valued parameter description. Just like ParamDesc, except 2293101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a 2303101Sstever@eecs.umich.edu# single value. 2313101Sstever@eecs.umich.edu 2323101Sstever@eecs.umich.educlass VectorParamValue(list): 2335033Smilesck@eecs.umich.edu __metaclass__ = MetaParamValue 2345475Snate@binkert.org def __setattr__(self, attr, value): 2355475Snate@binkert.org raise AttributeError, \ 2365475Snate@binkert.org "Not allowed to set %s on '%s'" % (attr, type(self).__name__) 2375475Snate@binkert.org 23810380SAndrew.Bardsley@arm.com def config_value(self): 23910380SAndrew.Bardsley@arm.com return [v.config_value() for v in self] 24010380SAndrew.Bardsley@arm.com 2413101Sstever@eecs.umich.edu def ini_str(self): 2423101Sstever@eecs.umich.edu return ' '.join([v.ini_str() for v in self]) 2433101Sstever@eecs.umich.edu 2444762Snate@binkert.org def getValue(self): 2454762Snate@binkert.org return [ v.getValue() for v in self ] 2464762Snate@binkert.org 2473101Sstever@eecs.umich.edu def unproxy(self, base): 2488460SAli.Saidi@ARM.com if len(self) == 1 and isinstance(self[0], proxy.BaseProxy): 2498459SAli.Saidi@ARM.com # The value is a proxy (e.g. Parent.any, Parent.all or 2508459SAli.Saidi@ARM.com # Parent.x) therefore try resolve it 2518459SAli.Saidi@ARM.com return self[0].unproxy(base) 2523101Sstever@eecs.umich.edu else: 2537528Ssteve.reinhardt@amd.com return [v.unproxy(base) for v in self] 2547528Ssteve.reinhardt@amd.com 2557528Ssteve.reinhardt@amd.comclass SimObjectVector(VectorParamValue): 2567528Ssteve.reinhardt@amd.com # support clone operation 2577528Ssteve.reinhardt@amd.com def __call__(self, **kwargs): 2587528Ssteve.reinhardt@amd.com return SimObjectVector([v(**kwargs) for v in self]) 2593101Sstever@eecs.umich.edu 2607528Ssteve.reinhardt@amd.com def clear_parent(self, old_parent): 2617528Ssteve.reinhardt@amd.com for v in self: 2627528Ssteve.reinhardt@amd.com v.clear_parent(old_parent) 2637528Ssteve.reinhardt@amd.com 2647528Ssteve.reinhardt@amd.com def set_parent(self, parent, name): 2657528Ssteve.reinhardt@amd.com if len(self) == 1: 2667528Ssteve.reinhardt@amd.com self[0].set_parent(parent, name) 2677528Ssteve.reinhardt@amd.com else: 2687528Ssteve.reinhardt@amd.com width = int(math.ceil(math.log(len(self))/math.log(10))) 2697528Ssteve.reinhardt@amd.com for i,v in enumerate(self): 2708321Ssteve.reinhardt@amd.com v.set_parent(parent, "%s%0*d" % (name, width, i)) 2718321Ssteve.reinhardt@amd.com 2727528Ssteve.reinhardt@amd.com def has_parent(self): 2737528Ssteve.reinhardt@amd.com return any([e.has_parent() for e in self if not isNullPointer(e)]) 2747528Ssteve.reinhardt@amd.com 2757528Ssteve.reinhardt@amd.com # return 'cpu0 cpu1' etc. for print_ini() 2767528Ssteve.reinhardt@amd.com def get_name(self): 2777528Ssteve.reinhardt@amd.com return ' '.join([v._name for v in self]) 2787528Ssteve.reinhardt@amd.com 2797528Ssteve.reinhardt@amd.com # By iterating through the constituent members of the vector here 2807528Ssteve.reinhardt@amd.com # we can nicely handle iterating over all a SimObject's children 2817528Ssteve.reinhardt@amd.com # without having to provide lots of special functions on 2827528Ssteve.reinhardt@amd.com # SimObjectVector directly. 2837528Ssteve.reinhardt@amd.com def descendants(self): 2847528Ssteve.reinhardt@amd.com for v in self: 2853101Sstever@eecs.umich.edu for obj in v.descendants(): 2868664SAli.Saidi@ARM.com yield obj 2878664SAli.Saidi@ARM.com 2888664SAli.Saidi@ARM.com def get_config_as_dict(self): 2898664SAli.Saidi@ARM.com a = [] 2908664SAli.Saidi@ARM.com for v in self: 2918664SAli.Saidi@ARM.com a.append(v.get_config_as_dict()) 2929953Sgeoffrey.blake@arm.com return a 2939953Sgeoffrey.blake@arm.com 2949953Sgeoffrey.blake@arm.com # If we are replacing an item in the vector, make sure to set the 2959953Sgeoffrey.blake@arm.com # parent reference of the new SimObject to be the same as the parent 2969953Sgeoffrey.blake@arm.com # of the SimObject being replaced. Useful to have if we created 2979953Sgeoffrey.blake@arm.com # a SimObjectVector of temporary objects that will be modified later in 2989953Sgeoffrey.blake@arm.com # configuration scripts. 2999953Sgeoffrey.blake@arm.com def __setitem__(self, key, value): 3009953Sgeoffrey.blake@arm.com val = self[key] 3019953Sgeoffrey.blake@arm.com if value.has_parent(): 3029953Sgeoffrey.blake@arm.com warn("SimObject %s already has a parent" % value.get_name() +\ 3039953Sgeoffrey.blake@arm.com " that is being overwritten by a SimObjectVector") 3049953Sgeoffrey.blake@arm.com value.set_parent(val.get_parent(), val._name) 30510267SGeoffrey.Blake@arm.com super(SimObjectVector, self).__setitem__(key, value) 30610267SGeoffrey.Blake@arm.com 30710267SGeoffrey.Blake@arm.com # Enumerate the params of each member of the SimObject vector. Creates 30810267SGeoffrey.Blake@arm.com # strings that will allow indexing into the vector by the python code and 30910267SGeoffrey.Blake@arm.com # allow it to be specified on the command line. 31010267SGeoffrey.Blake@arm.com def enumerateParams(self, flags_dict = {}, 31110267SGeoffrey.Blake@arm.com cmd_line_str = "", 31210267SGeoffrey.Blake@arm.com access_str = ""): 31310267SGeoffrey.Blake@arm.com if hasattr(self, "_paramEnumed"): 31410267SGeoffrey.Blake@arm.com print "Cycle detected enumerating params at %s?!" % (cmd_line_str) 31510267SGeoffrey.Blake@arm.com else: 31610267SGeoffrey.Blake@arm.com x = 0 31710267SGeoffrey.Blake@arm.com for vals in self: 31810267SGeoffrey.Blake@arm.com # Each entry in the SimObjectVector should be an 31910267SGeoffrey.Blake@arm.com # instance of a SimObject 32010267SGeoffrey.Blake@arm.com flags_dict = vals.enumerateParams(flags_dict, 32110267SGeoffrey.Blake@arm.com cmd_line_str + "%d." % x, 32210267SGeoffrey.Blake@arm.com access_str + "[%d]." % x) 32310267SGeoffrey.Blake@arm.com x = x + 1 32410267SGeoffrey.Blake@arm.com 3253101Sstever@eecs.umich.edu return flags_dict 3263101Sstever@eecs.umich.edu 3273101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc): 3283101Sstever@eecs.umich.edu # Convert assigned value to appropriate type. If the RHS is not a 3293101Sstever@eecs.umich.edu # list or tuple, it generates a single-element list. 3303101Sstever@eecs.umich.edu def convert(self, value): 3313101Sstever@eecs.umich.edu if isinstance(value, (list, tuple)): 33210364SGeoffrey.Blake@arm.com # list: coerce each element into new list 33310364SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) for v in value ] 33410364SGeoffrey.Blake@arm.com elif isinstance(value, str): 33510364SGeoffrey.Blake@arm.com # If input is a csv string 3363101Sstever@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) \ 3374762Snate@binkert.org for v in value.strip('[').strip(']').split(',') ] 3384762Snate@binkert.org else: 3394762Snate@binkert.org # singleton: coerce to a single-element list 3404762Snate@binkert.org tmp_list = [ ParamDesc.convert(self, value) ] 3417528Ssteve.reinhardt@amd.com 3424762Snate@binkert.org if isSimObjectSequence(tmp_list): 3434762Snate@binkert.org return SimObjectVector(tmp_list) 3444762Snate@binkert.org else: 34510267SGeoffrey.Blake@arm.com return VectorParamValue(tmp_list) 34610267SGeoffrey.Blake@arm.com 34710267SGeoffrey.Blake@arm.com # Produce a human readable example string that describes 34810267SGeoffrey.Blake@arm.com # how to set this vector parameter in the absence of a default 34910267SGeoffrey.Blake@arm.com # value. 35010267SGeoffrey.Blake@arm.com def example_str(self): 35110267SGeoffrey.Blake@arm.com s = super(VectorParamDesc, self).example_str() 35210267SGeoffrey.Blake@arm.com help_str = "[" + s + "," + s + ", ...]" 35310267SGeoffrey.Blake@arm.com return help_str 35410267SGeoffrey.Blake@arm.com 35510267SGeoffrey.Blake@arm.com # Produce a human readable representation of the value of this vector param. 35610267SGeoffrey.Blake@arm.com def pretty_print(self, value): 35710267SGeoffrey.Blake@arm.com if isinstance(value, (list, tuple)): 35810267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ] 35910267SGeoffrey.Blake@arm.com elif isinstance(value, str): 36010267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ] 36110267SGeoffrey.Blake@arm.com else: 36210267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.pretty_print(self, value) ] 36310267SGeoffrey.Blake@arm.com 36410267SGeoffrey.Blake@arm.com return tmp_list 36510267SGeoffrey.Blake@arm.com 36610267SGeoffrey.Blake@arm.com # This is a helper function for the new config system 36710267SGeoffrey.Blake@arm.com def __call__(self, value): 36810267SGeoffrey.Blake@arm.com if isinstance(value, (list, tuple)): 36910267SGeoffrey.Blake@arm.com # list: coerce each element into new list 37010267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) for v in value ] 37110364SGeoffrey.Blake@arm.com elif isinstance(value, str): 37210364SGeoffrey.Blake@arm.com # If input is a csv string 37310267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, v) \ 37410267SGeoffrey.Blake@arm.com for v in value.strip('[').strip(']').split(',') ] 37510267SGeoffrey.Blake@arm.com else: 37610267SGeoffrey.Blake@arm.com # singleton: coerce to a single-element list 37710267SGeoffrey.Blake@arm.com tmp_list = [ ParamDesc.convert(self, value) ] 37810267SGeoffrey.Blake@arm.com 3797673Snate@binkert.org return VectorParamValue(tmp_list) 3807673Snate@binkert.org 3817673Snate@binkert.org def cxx_predecls(self, code): 3823101Sstever@eecs.umich.edu code('#include <vector>') 38311988Sandreas.sandberg@arm.com self.ptype.cxx_predecls(code) 38411988Sandreas.sandberg@arm.com 38511988Sandreas.sandberg@arm.com def pybind_predecls(self, code): 38611988Sandreas.sandberg@arm.com code('#include <vector>') 3877673Snate@binkert.org self.ptype.pybind_predecls(code) 3887673Snate@binkert.org 3893101Sstever@eecs.umich.edu def cxx_decl(self, code): 3903101Sstever@eecs.umich.edu code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};') 3913101Sstever@eecs.umich.edu 3923101Sstever@eecs.umich.educlass ParamFactory(object): 3933101Sstever@eecs.umich.edu def __init__(self, param_desc_class, ptype_str = None): 3943101Sstever@eecs.umich.edu self.param_desc_class = param_desc_class 3953101Sstever@eecs.umich.edu self.ptype_str = ptype_str 3963101Sstever@eecs.umich.edu 3973101Sstever@eecs.umich.edu def __getattr__(self, attr): 3983101Sstever@eecs.umich.edu if self.ptype_str: 3993101Sstever@eecs.umich.edu attr = self.ptype_str + '.' + attr 4003101Sstever@eecs.umich.edu return ParamFactory(self.param_desc_class, attr) 4013101Sstever@eecs.umich.edu 4023101Sstever@eecs.umich.edu # E.g., Param.Int(5, "number of widgets") 4033101Sstever@eecs.umich.edu def __call__(self, *args, **kwargs): 4045033Smilesck@eecs.umich.edu ptype = None 4055033Smilesck@eecs.umich.edu try: 4063101Sstever@eecs.umich.edu ptype = allParams[self.ptype_str] 4073101Sstever@eecs.umich.edu except KeyError: 4083101Sstever@eecs.umich.edu # if name isn't defined yet, assume it's a SimObject, and 4093101Sstever@eecs.umich.edu # try to resolve it later 4103101Sstever@eecs.umich.edu pass 4113101Sstever@eecs.umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 4123101Sstever@eecs.umich.edu 4133101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc) 4143101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc) 4153101Sstever@eecs.umich.edu 4163101Sstever@eecs.umich.edu##################################################################### 4173101Sstever@eecs.umich.edu# 4183101Sstever@eecs.umich.edu# Parameter Types 4193101Sstever@eecs.umich.edu# 4203101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types 4213101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more 4223101Sstever@eecs.umich.edu# flexible to define our own set of types. This gives us more control 4233101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the 4243101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via 4253101Sstever@eecs.umich.edu# the __str__() conversion method). 4263101Sstever@eecs.umich.edu# 4273101Sstever@eecs.umich.edu##################################################################### 4283101Sstever@eecs.umich.edu 4293101Sstever@eecs.umich.edu# String-valued parameter. Just mixin the ParamValue class with the 4303101Sstever@eecs.umich.edu# built-in str class. 43110267SGeoffrey.Blake@arm.comclass String(ParamValue,str): 4327673Snate@binkert.org cxx_type = 'std::string' 4337673Snate@binkert.org cmd_line_settable = True 4347673Snate@binkert.org 4357673Snate@binkert.org @classmethod 4367673Snate@binkert.org def cxx_predecls(self, code): 43710267SGeoffrey.Blake@arm.com code('#include <string>') 43810267SGeoffrey.Blake@arm.com 43910267SGeoffrey.Blake@arm.com def __call__(self, value): 44010267SGeoffrey.Blake@arm.com self = value 44110458Sandreas.hansson@arm.com return value 44210458Sandreas.hansson@arm.com 44310458Sandreas.hansson@arm.com @classmethod 44410458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 44510458Sandreas.hansson@arm.com code('%s = %s;' % (dest, src)) 4464762Snate@binkert.org code('%s true;' % ret) 4474762Snate@binkert.org 4483101Sstever@eecs.umich.edu def getValue(self): 4493101Sstever@eecs.umich.edu return self 4503101Sstever@eecs.umich.edu 4513101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math 4523101Sstever@eecs.umich.edu# operations in a type-safe way. e.g., a Latency times an int returns 4533101Sstever@eecs.umich.edu# a new Latency object. 4543101Sstever@eecs.umich.educlass NumericParamValue(ParamValue): 4553101Sstever@eecs.umich.edu def __str__(self): 4563101Sstever@eecs.umich.edu return str(self.value) 4573101Sstever@eecs.umich.edu 4583101Sstever@eecs.umich.edu def __float__(self): 4593714Sstever@eecs.umich.edu return float(self.value) 4603714Sstever@eecs.umich.edu 4613714Sstever@eecs.umich.edu def __long__(self): 4623714Sstever@eecs.umich.edu return long(self.value) 4633714Sstever@eecs.umich.edu 4643714Sstever@eecs.umich.edu def __int__(self): 4653101Sstever@eecs.umich.edu return int(self.value) 4663101Sstever@eecs.umich.edu 4673101Sstever@eecs.umich.edu # hook for bounds checking 4683101Sstever@eecs.umich.edu def _check(self): 4693101Sstever@eecs.umich.edu return 4703101Sstever@eecs.umich.edu 4713101Sstever@eecs.umich.edu def __mul__(self, other): 4723101Sstever@eecs.umich.edu newobj = self.__class__(self) 4733101Sstever@eecs.umich.edu newobj.value *= other 4743101Sstever@eecs.umich.edu newobj._check() 4753101Sstever@eecs.umich.edu return newobj 4763101Sstever@eecs.umich.edu 4773101Sstever@eecs.umich.edu __rmul__ = __mul__ 4783101Sstever@eecs.umich.edu 4793101Sstever@eecs.umich.edu def __div__(self, other): 4803101Sstever@eecs.umich.edu newobj = self.__class__(self) 4813101Sstever@eecs.umich.edu newobj.value /= other 4823101Sstever@eecs.umich.edu newobj._check() 4833101Sstever@eecs.umich.edu return newobj 4843101Sstever@eecs.umich.edu 4853101Sstever@eecs.umich.edu def __sub__(self, other): 4863101Sstever@eecs.umich.edu newobj = self.__class__(self) 4873101Sstever@eecs.umich.edu newobj.value -= other 4883101Sstever@eecs.umich.edu newobj._check() 48910380SAndrew.Bardsley@arm.com return newobj 49010380SAndrew.Bardsley@arm.com 49110380SAndrew.Bardsley@arm.com def config_value(self): 49210458Sandreas.hansson@arm.com return self.value 49310458Sandreas.hansson@arm.com 49410458Sandreas.hansson@arm.com @classmethod 49510458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 49610458Sandreas.hansson@arm.com # Assume that base/str.hh will be included anyway 49710458Sandreas.hansson@arm.com # code('#include "base/str.hh"') 49810458Sandreas.hansson@arm.com pass 49910458Sandreas.hansson@arm.com 50010458Sandreas.hansson@arm.com # The default for parsing PODs from an .ini entry is to extract from an 50110458Sandreas.hansson@arm.com # istringstream and let overloading choose the right type according to 50210458Sandreas.hansson@arm.com # the dest type. 50310458Sandreas.hansson@arm.com @classmethod 50410458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 5053101Sstever@eecs.umich.edu code('%s to_number(%s, %s);' % (ret, src, dest)) 5065033Smilesck@eecs.umich.edu 5073101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters. See CheckedInt. 5083101Sstever@eecs.umich.educlass CheckedIntType(MetaParamValue): 5093101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 5103101Sstever@eecs.umich.edu super(CheckedIntType, cls).__init__(name, bases, dict) 5113101Sstever@eecs.umich.edu 5123101Sstever@eecs.umich.edu # CheckedInt is an abstract base class, so we actually don't 5133101Sstever@eecs.umich.edu # want to do any processing on it... the rest of this code is 5143101Sstever@eecs.umich.edu # just for classes that derive from CheckedInt. 5153101Sstever@eecs.umich.edu if name == 'CheckedInt': 5163101Sstever@eecs.umich.edu return 5173101Sstever@eecs.umich.edu 5183101Sstever@eecs.umich.edu if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 5195822Ssaidi@eecs.umich.edu if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 5205822Ssaidi@eecs.umich.edu panic("CheckedInt subclass %s must define either\n" \ 5213101Sstever@eecs.umich.edu " 'min' and 'max' or 'size' and 'unsigned'\n", 5223101Sstever@eecs.umich.edu name); 5233101Sstever@eecs.umich.edu if cls.unsigned: 5243101Sstever@eecs.umich.edu cls.min = 0 5253101Sstever@eecs.umich.edu cls.max = 2 ** cls.size - 1 5263101Sstever@eecs.umich.edu else: 5273101Sstever@eecs.umich.edu cls.min = -(2 ** (cls.size - 1)) 5283101Sstever@eecs.umich.edu cls.max = (2 ** (cls.size - 1)) - 1 5293101Sstever@eecs.umich.edu 5303101Sstever@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters. This 5313101Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific 5323101Sstever@eecs.umich.edu# bounds. Initialization of the min and max bounds is done in the 5333101Sstever@eecs.umich.edu# metaclass CheckedIntType.__init__. 53410267SGeoffrey.Blake@arm.comclass CheckedInt(NumericParamValue): 5353101Sstever@eecs.umich.edu __metaclass__ = CheckedIntType 5363101Sstever@eecs.umich.edu cmd_line_settable = True 5373101Sstever@eecs.umich.edu 5383101Sstever@eecs.umich.edu def _check(self): 5393101Sstever@eecs.umich.edu if not self.min <= self.value <= self.max: 5403101Sstever@eecs.umich.edu raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 5413101Sstever@eecs.umich.edu (self.min, self.value, self.max) 5423101Sstever@eecs.umich.edu 5433102Sstever@eecs.umich.edu def __init__(self, value): 5443714Sstever@eecs.umich.edu if isinstance(value, str): 5453101Sstever@eecs.umich.edu self.value = convert.toInteger(value) 5463714Sstever@eecs.umich.edu elif isinstance(value, (int, long, float, NumericParamValue)): 5473714Sstever@eecs.umich.edu self.value = long(value) 5483714Sstever@eecs.umich.edu else: 5493101Sstever@eecs.umich.edu raise TypeError, "Can't convert object of type %s to CheckedInt" \ 5503101Sstever@eecs.umich.edu % type(value).__name__ 55110267SGeoffrey.Blake@arm.com self._check() 55210267SGeoffrey.Blake@arm.com 55310267SGeoffrey.Blake@arm.com def __call__(self, value): 55410267SGeoffrey.Blake@arm.com self.__init__(value) 5557673Snate@binkert.org return value 5567673Snate@binkert.org 5577673Snate@binkert.org @classmethod 5587673Snate@binkert.org def cxx_predecls(cls, code): 5597673Snate@binkert.org # most derived types require this, so we just do it here once 5604762Snate@binkert.org code('#include "base/types.hh"') 5614762Snate@binkert.org 5624762Snate@binkert.org def getValue(self): 5633101Sstever@eecs.umich.edu return long(self.value) 5643101Sstever@eecs.umich.edu 5653101Sstever@eecs.umich.educlass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 5663101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 5673101Sstever@eecs.umich.edu 5683101Sstever@eecs.umich.educlass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 5693101Sstever@eecs.umich.educlass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 5703101Sstever@eecs.umich.educlass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 5713101Sstever@eecs.umich.educlass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 5723101Sstever@eecs.umich.educlass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 5733101Sstever@eecs.umich.educlass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 5743101Sstever@eecs.umich.educlass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 5753101Sstever@eecs.umich.educlass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 5763101Sstever@eecs.umich.edu 5773101Sstever@eecs.umich.educlass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 5783101Sstever@eecs.umich.educlass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 5793101Sstever@eecs.umich.educlass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 5803101Sstever@eecs.umich.educlass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 5813101Sstever@eecs.umich.edu 5829184Sandreas.hansson@arm.comclass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 5839184Sandreas.hansson@arm.com 5849184Sandreas.hansson@arm.comclass Cycles(CheckedInt): 5859184Sandreas.hansson@arm.com cxx_type = 'Cycles' 5869184Sandreas.hansson@arm.com size = 64 5879184Sandreas.hansson@arm.com unsigned = True 58811802Sandreas.sandberg@arm.com 5899184Sandreas.hansson@arm.com def getValue(self): 5909184Sandreas.hansson@arm.com from _m5.core import Cycles 59110458Sandreas.hansson@arm.com return Cycles(self.value) 59210458Sandreas.hansson@arm.com 59310458Sandreas.hansson@arm.com @classmethod 59410458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 59510458Sandreas.hansson@arm.com # Assume that base/str.hh will be included anyway 59610458Sandreas.hansson@arm.com # code('#include "base/str.hh"') 59710458Sandreas.hansson@arm.com pass 59810458Sandreas.hansson@arm.com 59910458Sandreas.hansson@arm.com @classmethod 60010458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 60110458Sandreas.hansson@arm.com code('uint64_t _temp;') 60210458Sandreas.hansson@arm.com code('bool _ret = to_number(%s, _temp);' % src) 60310458Sandreas.hansson@arm.com code('if (_ret)') 60410458Sandreas.hansson@arm.com code(' %s = Cycles(_temp);' % dest) 6053101Sstever@eecs.umich.edu code('%s _ret;' % ret) 6064446Sbinkertn@umich.edu 60710668SGeoffrey.Blake@arm.comclass Float(ParamValue, float): 6083101Sstever@eecs.umich.edu cxx_type = 'double' 6095468Snate@binkert.org cmd_line_settable = True 61010267SGeoffrey.Blake@arm.com 6115468Snate@binkert.org def __init__(self, value): 6125468Snate@binkert.org if isinstance(value, (int, long, float, NumericParamValue, Float, str)): 6135468Snate@binkert.org self.value = float(value) 6145468Snate@binkert.org else: 6155468Snate@binkert.org raise TypeError, "Can't convert object of type %s to Float" \ 61610267SGeoffrey.Blake@arm.com % type(value).__name__ 61710267SGeoffrey.Blake@arm.com 61810267SGeoffrey.Blake@arm.com def __call__(self, value): 61910267SGeoffrey.Blake@arm.com self.__init__(value) 6204762Snate@binkert.org return value 6214762Snate@binkert.org 6224762Snate@binkert.org def getValue(self): 62310380SAndrew.Bardsley@arm.com return float(self.value) 62410380SAndrew.Bardsley@arm.com 62510380SAndrew.Bardsley@arm.com def config_value(self): 62610458Sandreas.hansson@arm.com return self 62710458Sandreas.hansson@arm.com 62810458Sandreas.hansson@arm.com @classmethod 62910458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 63010458Sandreas.hansson@arm.com code('#include <sstream>') 63110458Sandreas.hansson@arm.com 63210458Sandreas.hansson@arm.com @classmethod 63310458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 6343101Sstever@eecs.umich.edu code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 6353101Sstever@eecs.umich.edu 63610267SGeoffrey.Blake@arm.comclass MemorySize(CheckedInt): 6373101Sstever@eecs.umich.edu cxx_type = 'uint64_t' 6383101Sstever@eecs.umich.edu ex_str = '512MB' 6393101Sstever@eecs.umich.edu size = 64 6403101Sstever@eecs.umich.edu unsigned = True 6413101Sstever@eecs.umich.edu def __init__(self, value): 6423101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 6433102Sstever@eecs.umich.edu self.value = value.value 6443101Sstever@eecs.umich.edu else: 6453101Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 6463101Sstever@eecs.umich.edu self._check() 6474168Sbinkertn@umich.edu 64810267SGeoffrey.Blake@arm.comclass MemorySize32(CheckedInt): 6493101Sstever@eecs.umich.edu cxx_type = 'uint32_t' 6503101Sstever@eecs.umich.edu ex_str = '512MB' 6513101Sstever@eecs.umich.edu size = 32 6523101Sstever@eecs.umich.edu unsigned = True 6533101Sstever@eecs.umich.edu def __init__(self, value): 6543101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 6553102Sstever@eecs.umich.edu self.value = value.value 6563101Sstever@eecs.umich.edu else: 6573101Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 6583101Sstever@eecs.umich.edu self._check() 6593101Sstever@eecs.umich.edu 6603101Sstever@eecs.umich.educlass Addr(CheckedInt): 6613101Sstever@eecs.umich.edu cxx_type = 'Addr' 6623101Sstever@eecs.umich.edu size = 64 6633101Sstever@eecs.umich.edu unsigned = True 6643101Sstever@eecs.umich.edu def __init__(self, value): 6653101Sstever@eecs.umich.edu if isinstance(value, Addr): 6663101Sstever@eecs.umich.edu self.value = value.value 66710317Smitch.hayenga@arm.com else: 66810317Smitch.hayenga@arm.com try: 66910317Smitch.hayenga@arm.com # Often addresses are referred to with sizes. Ex: A device 67010317Smitch.hayenga@arm.com # base address is at "512MB". Use toMemorySize() to convert 67110317Smitch.hayenga@arm.com # these into addresses. If the address is not specified with a 6723102Sstever@eecs.umich.edu # "size", an exception will occur and numeric translation will 67310317Smitch.hayenga@arm.com # proceed below. 67410317Smitch.hayenga@arm.com self.value = convert.toMemorySize(value) 67510317Smitch.hayenga@arm.com except (TypeError, ValueError): 67610317Smitch.hayenga@arm.com # Convert number to string and use long() to do automatic 67710317Smitch.hayenga@arm.com # base conversion (requires base=0 for auto-conversion) 6783101Sstever@eecs.umich.edu self.value = long(str(value), base=0) 6793584Ssaidi@eecs.umich.edu 6803584Ssaidi@eecs.umich.edu self._check() 6813584Ssaidi@eecs.umich.edu def __add__(self, other): 6823584Ssaidi@eecs.umich.edu if isinstance(other, Addr): 6833584Ssaidi@eecs.umich.edu return self.value + other.value 68410267SGeoffrey.Blake@arm.com else: 68510267SGeoffrey.Blake@arm.com return self.value + other 68610267SGeoffrey.Blake@arm.com def pretty_print(self, value): 68710267SGeoffrey.Blake@arm.com try: 68810267SGeoffrey.Blake@arm.com val = convert.toMemorySize(value) 68910267SGeoffrey.Blake@arm.com except TypeError: 6903101Sstever@eecs.umich.edu val = long(value) 6919232Sandreas.hansson@arm.com return "0x%x" % long(val) 6929235Sandreas.hansson@arm.com 6933101Sstever@eecs.umich.educlass AddrRange(ParamValue): 6943101Sstever@eecs.umich.edu cxx_type = 'AddrRange' 69510676Sandreas.hansson@arm.com 6969411Sandreas.hansson@arm.com def __init__(self, *args, **kwargs): 69710676Sandreas.hansson@arm.com # Disable interleaving and hashing by default 6989411Sandreas.hansson@arm.com self.intlvHighBit = 0 6999411Sandreas.hansson@arm.com self.xorHighBit = 0 7009411Sandreas.hansson@arm.com self.intlvBits = 0 7013101Sstever@eecs.umich.edu self.intlvMatch = 0 7029411Sandreas.hansson@arm.com 7039411Sandreas.hansson@arm.com def handle_kwargs(self, kwargs): 7049411Sandreas.hansson@arm.com # An address range needs to have an upper limit, specified 7053101Sstever@eecs.umich.edu # either explicitly with an end, or as an offset using the 7069232Sandreas.hansson@arm.com # size keyword. 7073101Sstever@eecs.umich.edu if 'end' in kwargs: 7089232Sandreas.hansson@arm.com self.end = Addr(kwargs.pop('end')) 7093101Sstever@eecs.umich.edu elif 'size' in kwargs: 7103101Sstever@eecs.umich.edu self.end = self.start + Addr(kwargs.pop('size')) - 1 7113101Sstever@eecs.umich.edu else: 7129411Sandreas.hansson@arm.com raise TypeError, "Either end or size must be specified" 7139411Sandreas.hansson@arm.com 7149411Sandreas.hansson@arm.com # Now on to the optional bit 71510676Sandreas.hansson@arm.com if 'intlvHighBit' in kwargs: 71610676Sandreas.hansson@arm.com self.intlvHighBit = int(kwargs.pop('intlvHighBit')) 7179411Sandreas.hansson@arm.com if 'xorHighBit' in kwargs: 7189411Sandreas.hansson@arm.com self.xorHighBit = int(kwargs.pop('xorHighBit')) 7199411Sandreas.hansson@arm.com if 'intlvBits' in kwargs: 7209411Sandreas.hansson@arm.com self.intlvBits = int(kwargs.pop('intlvBits')) 7219411Sandreas.hansson@arm.com if 'intlvMatch' in kwargs: 7223101Sstever@eecs.umich.edu self.intlvMatch = int(kwargs.pop('intlvMatch')) 7239232Sandreas.hansson@arm.com 7243101Sstever@eecs.umich.edu if len(args) == 0: 7253101Sstever@eecs.umich.edu self.start = Addr(kwargs.pop('start')) 7263101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 7273101Sstever@eecs.umich.edu 7289232Sandreas.hansson@arm.com elif len(args) == 1: 7293101Sstever@eecs.umich.edu if kwargs: 7305219Ssaidi@eecs.umich.edu self.start = Addr(args[0]) 7319232Sandreas.hansson@arm.com handle_kwargs(self, kwargs) 7329232Sandreas.hansson@arm.com elif isinstance(args[0], (list, tuple)): 7333101Sstever@eecs.umich.edu self.start = Addr(args[0][0]) 7349232Sandreas.hansson@arm.com self.end = Addr(args[0][1]) 7359232Sandreas.hansson@arm.com else: 7363101Sstever@eecs.umich.edu self.start = Addr(0) 7373101Sstever@eecs.umich.edu self.end = Addr(args[0]) - 1 7389232Sandreas.hansson@arm.com 7399232Sandreas.hansson@arm.com elif len(args) == 2: 7403101Sstever@eecs.umich.edu self.start = Addr(args[0]) 7413101Sstever@eecs.umich.edu self.end = Addr(args[1]) 7423101Sstever@eecs.umich.edu else: 7433101Sstever@eecs.umich.edu raise TypeError, "Too many arguments specified" 7449232Sandreas.hansson@arm.com 7453101Sstever@eecs.umich.edu if kwargs: 7463101Sstever@eecs.umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 74711620SMatthew.Poremba@amd.com 74811620SMatthew.Poremba@amd.com def __str__(self): 74911620SMatthew.Poremba@amd.com return '%s:%s:%s:%s:%s:%s' \ 7509232Sandreas.hansson@arm.com % (self.start, self.end, self.intlvHighBit, self.xorHighBit,\ 7519232Sandreas.hansson@arm.com self.intlvBits, self.intlvMatch) 7529411Sandreas.hansson@arm.com 7539411Sandreas.hansson@arm.com def size(self): 7543101Sstever@eecs.umich.edu # Divide the size by the size of the interleaving slice 7557673Snate@binkert.org return (long(self.end) - long(self.start) + 1) >> self.intlvBits 7567673Snate@binkert.org 7579232Sandreas.hansson@arm.com @classmethod 7589235Sandreas.hansson@arm.com def cxx_predecls(cls, code): 7597675Snate@binkert.org Addr.cxx_predecls(code) 7607675Snate@binkert.org code('#include "base/addr_range.hh"') 76111988Sandreas.sandberg@arm.com 76211988Sandreas.sandberg@arm.com @classmethod 76311988Sandreas.sandberg@arm.com def pybind_predecls(cls, code): 76411988Sandreas.sandberg@arm.com Addr.pybind_predecls(code) 76511988Sandreas.sandberg@arm.com code('#include "base/addr_range.hh"') 76610458Sandreas.hansson@arm.com 76710458Sandreas.hansson@arm.com @classmethod 76810458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 76910458Sandreas.hansson@arm.com code('#include <sstream>') 77010458Sandreas.hansson@arm.com 77111620SMatthew.Poremba@amd.com @classmethod 77211620SMatthew.Poremba@amd.com def cxx_ini_parse(cls, code, src, dest, ret): 77310458Sandreas.hansson@arm.com code('uint64_t _start, _end, _intlvHighBit = 0, _xorHighBit = 0;') 77410458Sandreas.hansson@arm.com code('uint64_t _intlvBits = 0, _intlvMatch = 0;') 77510458Sandreas.hansson@arm.com code('char _sep;') 77610458Sandreas.hansson@arm.com code('std::istringstream _stream(${src});') 77710458Sandreas.hansson@arm.com code('_stream >> _start;') 77811620SMatthew.Poremba@amd.com code('_stream.get(_sep);') 77911620SMatthew.Poremba@amd.com code('_stream >> _end;') 78011620SMatthew.Poremba@amd.com code('if (!_stream.fail() && !_stream.eof()) {') 78111620SMatthew.Poremba@amd.com code(' _stream.get(_sep);') 78211620SMatthew.Poremba@amd.com code(' _stream >> _intlvHighBit;') 78311620SMatthew.Poremba@amd.com code(' _stream.get(_sep);') 78411620SMatthew.Poremba@amd.com code(' _stream >> _xorHighBit;') 78511620SMatthew.Poremba@amd.com code(' _stream.get(_sep);') 78611620SMatthew.Poremba@amd.com code(' _stream >> _intlvBits;') 78711620SMatthew.Poremba@amd.com code(' _stream.get(_sep);') 78810458Sandreas.hansson@arm.com code(' _stream >> _intlvMatch;') 78910458Sandreas.hansson@arm.com code('}') 79010458Sandreas.hansson@arm.com code('bool _ret = !_stream.fail() &&' 79111620SMatthew.Poremba@amd.com '_stream.eof() && _sep == \':\';') 79211620SMatthew.Poremba@amd.com code('if (_ret)') 79310458Sandreas.hansson@arm.com code(' ${dest} = AddrRange(_start, _end, _intlvHighBit, \ 79410458Sandreas.hansson@arm.com _xorHighBit, _intlvBits, _intlvMatch);') 7954762Snate@binkert.org code('${ret} _ret;') 79611991Sandreas.sandberg@arm.com 79711802Sandreas.sandberg@arm.com def getValue(self): 7984762Snate@binkert.org # Go from the Python class to the wrapped C++ class 7999411Sandreas.hansson@arm.com from _m5.range import AddrRange 80010676Sandreas.hansson@arm.com 80110676Sandreas.hansson@arm.com return AddrRange(long(self.start), long(self.end), 8023101Sstever@eecs.umich.edu int(self.intlvHighBit), int(self.xorHighBit), 8033101Sstever@eecs.umich.edu int(self.intlvBits), int(self.intlvMatch)) 8043101Sstever@eecs.umich.edu 8053101Sstever@eecs.umich.edu# Boolean parameter type. Python doesn't let you subclass bool, since 8063101Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and 8073101Sstever@eecs.umich.edu# False. Thus this is a little more complicated than String. 80810267SGeoffrey.Blake@arm.comclass Bool(ParamValue): 80910267SGeoffrey.Blake@arm.com cxx_type = 'bool' 8103101Sstever@eecs.umich.edu cmd_line_settable = True 8113101Sstever@eecs.umich.edu 8123102Sstever@eecs.umich.edu def __init__(self, value): 8133101Sstever@eecs.umich.edu try: 8143101Sstever@eecs.umich.edu self.value = convert.toBool(value) 8153101Sstever@eecs.umich.edu except TypeError: 81610267SGeoffrey.Blake@arm.com self.value = bool(value) 81710267SGeoffrey.Blake@arm.com 81810267SGeoffrey.Blake@arm.com def __call__(self, value): 81910267SGeoffrey.Blake@arm.com self.__init__(value) 8204762Snate@binkert.org return value 8214762Snate@binkert.org 8224762Snate@binkert.org def getValue(self): 8233101Sstever@eecs.umich.edu return bool(self.value) 8243101Sstever@eecs.umich.edu 8253101Sstever@eecs.umich.edu def __str__(self): 8268934SBrad.Beckmann@amd.com return str(self.value) 8278934SBrad.Beckmann@amd.com 8288934SBrad.Beckmann@amd.com # implement truth value testing for Bool parameters so that these params 8298934SBrad.Beckmann@amd.com # evaluate correctly during the python configuration phase 8308934SBrad.Beckmann@amd.com def __nonzero__(self): 8313101Sstever@eecs.umich.edu return bool(self.value) 8323101Sstever@eecs.umich.edu 8333101Sstever@eecs.umich.edu def ini_str(self): 8343101Sstever@eecs.umich.edu if self.value: 8353101Sstever@eecs.umich.edu return 'true' 83610380SAndrew.Bardsley@arm.com return 'false' 83710380SAndrew.Bardsley@arm.com 83810380SAndrew.Bardsley@arm.com def config_value(self): 83910458Sandreas.hansson@arm.com return self.value 84010458Sandreas.hansson@arm.com 84110458Sandreas.hansson@arm.com @classmethod 84210458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 84310458Sandreas.hansson@arm.com # Assume that base/str.hh will be included anyway 84410458Sandreas.hansson@arm.com # code('#include "base/str.hh"') 84510458Sandreas.hansson@arm.com pass 84610458Sandreas.hansson@arm.com 84710458Sandreas.hansson@arm.com @classmethod 84810458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 8493101Sstever@eecs.umich.edu code('%s to_bool(%s, %s);' % (ret, src, dest)) 8503101Sstever@eecs.umich.edu 8513101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1): 8523101Sstever@eecs.umich.edu bytes = map(lambda x: int(x, 16), addr.split(':')) 8533101Sstever@eecs.umich.edu bytes[5] += val 8543101Sstever@eecs.umich.edu for i in (5, 4, 3, 2, 1): 8553101Sstever@eecs.umich.edu val,rem = divmod(bytes[i], 256) 8563101Sstever@eecs.umich.edu bytes[i] = rem 8573101Sstever@eecs.umich.edu if val == 0: 8583101Sstever@eecs.umich.edu break 8593101Sstever@eecs.umich.edu bytes[i - 1] += val 8603101Sstever@eecs.umich.edu assert(bytes[0] <= 255) 8614380Sbinkertn@umich.edu return ':'.join(map(lambda x: '%02x' % x, bytes)) 8624380Sbinkertn@umich.edu 8634380Sbinkertn@umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 8643101Sstever@eecs.umich.edudef NextEthernetAddr(): 8654380Sbinkertn@umich.edu global _NextEthernetAddr 8664380Sbinkertn@umich.edu 8674380Sbinkertn@umich.edu value = _NextEthernetAddr 8683101Sstever@eecs.umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 8693101Sstever@eecs.umich.edu return value 8703101Sstever@eecs.umich.edu 87110267SGeoffrey.Blake@arm.comclass EthernetAddr(ParamValue): 87210267SGeoffrey.Blake@arm.com cxx_type = 'Net::EthAddr' 8737673Snate@binkert.org ex_str = "00:90:00:00:00:01" 8747673Snate@binkert.org cmd_line_settable = True 8757673Snate@binkert.org 8767673Snate@binkert.org @classmethod 8777673Snate@binkert.org def cxx_predecls(cls, code): 8783101Sstever@eecs.umich.edu code('#include "base/inet.hh"') 8793101Sstever@eecs.umich.edu 8803101Sstever@eecs.umich.edu def __init__(self, value): 8813101Sstever@eecs.umich.edu if value == NextEthernetAddr: 8823101Sstever@eecs.umich.edu self.value = value 8833101Sstever@eecs.umich.edu return 8843101Sstever@eecs.umich.edu 8853101Sstever@eecs.umich.edu if not isinstance(value, str): 8863101Sstever@eecs.umich.edu raise TypeError, "expected an ethernet address and didn't get one" 8873101Sstever@eecs.umich.edu 8883101Sstever@eecs.umich.edu bytes = value.split(':') 8893101Sstever@eecs.umich.edu if len(bytes) != 6: 8903101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 8919941SGeoffrey.Blake@arm.com 8923101Sstever@eecs.umich.edu for byte in bytes: 8933101Sstever@eecs.umich.edu if not 0 <= int(byte, base=16) <= 0xff: 8943101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 8953101Sstever@eecs.umich.edu 89610267SGeoffrey.Blake@arm.com self.value = value 89710267SGeoffrey.Blake@arm.com 89810267SGeoffrey.Blake@arm.com def __call__(self, value): 89910267SGeoffrey.Blake@arm.com self.__init__(value) 9003101Sstever@eecs.umich.edu return value 9013101Sstever@eecs.umich.edu 9024380Sbinkertn@umich.edu def unproxy(self, base): 9033101Sstever@eecs.umich.edu if self.value == NextEthernetAddr: 9043101Sstever@eecs.umich.edu return EthernetAddr(self.value()) 9054762Snate@binkert.org return self 90611988Sandreas.sandberg@arm.com 9074762Snate@binkert.org def getValue(self): 9084762Snate@binkert.org from _m5.net import EthAddr 90911228SAndrew.Bardsley@arm.com return EthAddr(self.value) 91011228SAndrew.Bardsley@arm.com 91111228SAndrew.Bardsley@arm.com def __str__(self): 9124380Sbinkertn@umich.edu return self.value 9134380Sbinkertn@umich.edu 9143101Sstever@eecs.umich.edu def ini_str(self): 91510458Sandreas.hansson@arm.com return self.value 91610458Sandreas.hansson@arm.com 91710458Sandreas.hansson@arm.com @classmethod 91810458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 91910458Sandreas.hansson@arm.com code('%s = Net::EthAddr(%s);' % (dest, src)) 9207777Sgblack@eecs.umich.edu code('%s true;' % ret) 9217777Sgblack@eecs.umich.edu 9227777Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of 9237777Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP. 92410267SGeoffrey.Blake@arm.comclass IpAddress(ParamValue): 92510267SGeoffrey.Blake@arm.com cxx_type = 'Net::IpAddress' 9267777Sgblack@eecs.umich.edu ex_str = "127.0.0.1" 9277777Sgblack@eecs.umich.edu cmd_line_settable = True 9287777Sgblack@eecs.umich.edu 9297777Sgblack@eecs.umich.edu @classmethod 9307777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 9317777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 9327777Sgblack@eecs.umich.edu 9337777Sgblack@eecs.umich.edu def __init__(self, value): 9347777Sgblack@eecs.umich.edu if isinstance(value, IpAddress): 9357777Sgblack@eecs.umich.edu self.ip = value.ip 9367777Sgblack@eecs.umich.edu else: 9377777Sgblack@eecs.umich.edu try: 9387777Sgblack@eecs.umich.edu self.ip = convert.toIpAddress(value) 9397777Sgblack@eecs.umich.edu except TypeError: 9407777Sgblack@eecs.umich.edu self.ip = long(value) 94110267SGeoffrey.Blake@arm.com self.verifyIp() 94210267SGeoffrey.Blake@arm.com 94310267SGeoffrey.Blake@arm.com def __call__(self, value): 94410267SGeoffrey.Blake@arm.com self.__init__(value) 9458579Ssteve.reinhardt@amd.com return value 9468579Ssteve.reinhardt@amd.com 9478579Ssteve.reinhardt@amd.com def __str__(self): 9488579Ssteve.reinhardt@amd.com tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)] 9498579Ssteve.reinhardt@amd.com return '%d.%d.%d.%d' % tuple(tup) 9508579Ssteve.reinhardt@amd.com 9518579Ssteve.reinhardt@amd.com def __eq__(self, other): 9528579Ssteve.reinhardt@amd.com if isinstance(other, IpAddress): 9538579Ssteve.reinhardt@amd.com return self.ip == other.ip 9548579Ssteve.reinhardt@amd.com elif isinstance(other, str): 9558579Ssteve.reinhardt@amd.com try: 9568579Ssteve.reinhardt@amd.com return self.ip == convert.toIpAddress(other) 9578579Ssteve.reinhardt@amd.com except: 9588579Ssteve.reinhardt@amd.com return False 9598579Ssteve.reinhardt@amd.com else: 9608579Ssteve.reinhardt@amd.com return self.ip == other 9618579Ssteve.reinhardt@amd.com 9628579Ssteve.reinhardt@amd.com def __ne__(self, other): 9637777Sgblack@eecs.umich.edu return not (self == other) 9647777Sgblack@eecs.umich.edu 9657798Sgblack@eecs.umich.edu def verifyIp(self): 9667777Sgblack@eecs.umich.edu if self.ip < 0 or self.ip >= (1 << 32): 9677777Sgblack@eecs.umich.edu raise TypeError, "invalid ip address %#08x" % self.ip 96811988Sandreas.sandberg@arm.com 9697777Sgblack@eecs.umich.edu def getValue(self): 9707777Sgblack@eecs.umich.edu from _m5.net import IpAddress 9717777Sgblack@eecs.umich.edu return IpAddress(self.ip) 9727777Sgblack@eecs.umich.edu 9737777Sgblack@eecs.umich.edu# When initializing an IpNetmask, pass in an existing IpNetmask, a string of 9747777Sgblack@eecs.umich.edu# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as 9757777Sgblack@eecs.umich.edu# positional or keyword arguments. 97610267SGeoffrey.Blake@arm.comclass IpNetmask(IpAddress): 97710267SGeoffrey.Blake@arm.com cxx_type = 'Net::IpNetmask' 9787777Sgblack@eecs.umich.edu ex_str = "127.0.0.0/24" 9797777Sgblack@eecs.umich.edu cmd_line_settable = True 9807777Sgblack@eecs.umich.edu 9817777Sgblack@eecs.umich.edu @classmethod 9827777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 9837777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 9847777Sgblack@eecs.umich.edu 9857777Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 9867777Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 9877777Sgblack@eecs.umich.edu if key in kwargs: 9887777Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 9897777Sgblack@eecs.umich.edu elif elseVal: 9907777Sgblack@eecs.umich.edu setattr(self, key, elseVal) 9917777Sgblack@eecs.umich.edu else: 9927777Sgblack@eecs.umich.edu raise TypeError, "No value set for %s" % key 9937777Sgblack@eecs.umich.edu 9947777Sgblack@eecs.umich.edu if len(args) == 0: 9957777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip') 9967777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask') 9977777Sgblack@eecs.umich.edu 9987777Sgblack@eecs.umich.edu elif len(args) == 1: 9997777Sgblack@eecs.umich.edu if kwargs: 10007777Sgblack@eecs.umich.edu if not 'ip' in kwargs and not 'netmask' in kwargs: 10017777Sgblack@eecs.umich.edu raise TypeError, "Invalid arguments" 10027777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 10037777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'netmask', args[0]) 10047777Sgblack@eecs.umich.edu elif isinstance(args[0], IpNetmask): 10057777Sgblack@eecs.umich.edu self.ip = args[0].ip 10067777Sgblack@eecs.umich.edu self.netmask = args[0].netmask 10077777Sgblack@eecs.umich.edu else: 10087777Sgblack@eecs.umich.edu (self.ip, self.netmask) = convert.toIpNetmask(args[0]) 10097777Sgblack@eecs.umich.edu 10107777Sgblack@eecs.umich.edu elif len(args) == 2: 10117777Sgblack@eecs.umich.edu self.ip = args[0] 10127777Sgblack@eecs.umich.edu self.netmask = args[1] 10137777Sgblack@eecs.umich.edu else: 10147777Sgblack@eecs.umich.edu raise TypeError, "Too many arguments specified" 10157777Sgblack@eecs.umich.edu 10167777Sgblack@eecs.umich.edu if kwargs: 10177777Sgblack@eecs.umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 10187777Sgblack@eecs.umich.edu 101910267SGeoffrey.Blake@arm.com self.verify() 102010267SGeoffrey.Blake@arm.com 102110267SGeoffrey.Blake@arm.com def __call__(self, value): 102210267SGeoffrey.Blake@arm.com self.__init__(value) 10238579Ssteve.reinhardt@amd.com return value 10248579Ssteve.reinhardt@amd.com 10258579Ssteve.reinhardt@amd.com def __str__(self): 10268579Ssteve.reinhardt@amd.com return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask) 10278579Ssteve.reinhardt@amd.com 10288579Ssteve.reinhardt@amd.com def __eq__(self, other): 10298579Ssteve.reinhardt@amd.com if isinstance(other, IpNetmask): 10308579Ssteve.reinhardt@amd.com return self.ip == other.ip and self.netmask == other.netmask 10318579Ssteve.reinhardt@amd.com elif isinstance(other, str): 10328579Ssteve.reinhardt@amd.com try: 10338579Ssteve.reinhardt@amd.com return (self.ip, self.netmask) == convert.toIpNetmask(other) 10348579Ssteve.reinhardt@amd.com except: 10358579Ssteve.reinhardt@amd.com return False 10368579Ssteve.reinhardt@amd.com else: 10377777Sgblack@eecs.umich.edu return False 10387777Sgblack@eecs.umich.edu 10397777Sgblack@eecs.umich.edu def verify(self): 10407777Sgblack@eecs.umich.edu self.verifyIp() 10417777Sgblack@eecs.umich.edu if self.netmask < 0 or self.netmask > 32: 10427777Sgblack@eecs.umich.edu raise TypeError, "invalid netmask %d" % netmask 104311988Sandreas.sandberg@arm.com 10447777Sgblack@eecs.umich.edu def getValue(self): 10457777Sgblack@eecs.umich.edu from _m5.net import IpNetmask 10467777Sgblack@eecs.umich.edu return IpNetmask(self.ip, self.netmask) 10477777Sgblack@eecs.umich.edu 10487777Sgblack@eecs.umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of 10497777Sgblack@eecs.umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments. 105010267SGeoffrey.Blake@arm.comclass IpWithPort(IpAddress): 105110267SGeoffrey.Blake@arm.com cxx_type = 'Net::IpWithPort' 10527777Sgblack@eecs.umich.edu ex_str = "127.0.0.1:80" 10537777Sgblack@eecs.umich.edu cmd_line_settable = True 10547777Sgblack@eecs.umich.edu 10557777Sgblack@eecs.umich.edu @classmethod 10567777Sgblack@eecs.umich.edu def cxx_predecls(cls, code): 10577777Sgblack@eecs.umich.edu code('#include "base/inet.hh"') 10587777Sgblack@eecs.umich.edu 10597777Sgblack@eecs.umich.edu def __init__(self, *args, **kwargs): 10607777Sgblack@eecs.umich.edu def handle_kwarg(self, kwargs, key, elseVal = None): 10617777Sgblack@eecs.umich.edu if key in kwargs: 10627777Sgblack@eecs.umich.edu setattr(self, key, kwargs.pop(key)) 10637777Sgblack@eecs.umich.edu elif elseVal: 10647777Sgblack@eecs.umich.edu setattr(self, key, elseVal) 10657777Sgblack@eecs.umich.edu else: 10667777Sgblack@eecs.umich.edu raise TypeError, "No value set for %s" % key 10677777Sgblack@eecs.umich.edu 10687777Sgblack@eecs.umich.edu if len(args) == 0: 10697777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip') 10707777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'port') 10717777Sgblack@eecs.umich.edu 10727777Sgblack@eecs.umich.edu elif len(args) == 1: 10737777Sgblack@eecs.umich.edu if kwargs: 10747777Sgblack@eecs.umich.edu if not 'ip' in kwargs and not 'port' in kwargs: 10757777Sgblack@eecs.umich.edu raise TypeError, "Invalid arguments" 10767777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'ip', args[0]) 10777777Sgblack@eecs.umich.edu handle_kwarg(self, kwargs, 'port', args[0]) 10787777Sgblack@eecs.umich.edu elif isinstance(args[0], IpWithPort): 10797777Sgblack@eecs.umich.edu self.ip = args[0].ip 10807777Sgblack@eecs.umich.edu self.port = args[0].port 10817777Sgblack@eecs.umich.edu else: 10827777Sgblack@eecs.umich.edu (self.ip, self.port) = convert.toIpWithPort(args[0]) 10837777Sgblack@eecs.umich.edu 10847777Sgblack@eecs.umich.edu elif len(args) == 2: 10857777Sgblack@eecs.umich.edu self.ip = args[0] 10867777Sgblack@eecs.umich.edu self.port = args[1] 10877777Sgblack@eecs.umich.edu else: 10887777Sgblack@eecs.umich.edu raise TypeError, "Too many arguments specified" 10897777Sgblack@eecs.umich.edu 10907777Sgblack@eecs.umich.edu if kwargs: 10917777Sgblack@eecs.umich.edu raise TypeError, "Too many keywords: %s" % kwargs.keys() 10927777Sgblack@eecs.umich.edu 109310267SGeoffrey.Blake@arm.com self.verify() 109410267SGeoffrey.Blake@arm.com 109510267SGeoffrey.Blake@arm.com def __call__(self, value): 109610267SGeoffrey.Blake@arm.com self.__init__(value) 10978579Ssteve.reinhardt@amd.com return value 10988579Ssteve.reinhardt@amd.com 10998579Ssteve.reinhardt@amd.com def __str__(self): 11008579Ssteve.reinhardt@amd.com return "%s:%d" % (super(IpWithPort, self).__str__(), self.port) 11018579Ssteve.reinhardt@amd.com 11028579Ssteve.reinhardt@amd.com def __eq__(self, other): 11038579Ssteve.reinhardt@amd.com if isinstance(other, IpWithPort): 11048579Ssteve.reinhardt@amd.com return self.ip == other.ip and self.port == other.port 11058579Ssteve.reinhardt@amd.com elif isinstance(other, str): 11068579Ssteve.reinhardt@amd.com try: 11078579Ssteve.reinhardt@amd.com return (self.ip, self.port) == convert.toIpWithPort(other) 11088579Ssteve.reinhardt@amd.com except: 11098579Ssteve.reinhardt@amd.com return False 11108579Ssteve.reinhardt@amd.com else: 11117777Sgblack@eecs.umich.edu return False 11127777Sgblack@eecs.umich.edu 11137777Sgblack@eecs.umich.edu def verify(self): 11147777Sgblack@eecs.umich.edu self.verifyIp() 11157777Sgblack@eecs.umich.edu if self.port < 0 or self.port > 0xffff: 11167777Sgblack@eecs.umich.edu raise TypeError, "invalid port %d" % self.port 111711988Sandreas.sandberg@arm.com 11187777Sgblack@eecs.umich.edu def getValue(self): 11197777Sgblack@eecs.umich.edu from _m5.net import IpWithPort 11203932Sbinkertn@umich.edu return IpWithPort(self.ip, self.port) 112110380SAndrew.Bardsley@arm.com 11223932Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 11233932Sbinkertn@umich.edu "%a %b %d %H:%M:%S %Y", 11243932Sbinkertn@umich.edu "%Y/%m/%d %H:%M:%S", 11253932Sbinkertn@umich.edu "%Y/%m/%d %H:%M", 11263932Sbinkertn@umich.edu "%Y/%m/%d", 11273932Sbinkertn@umich.edu "%m/%d/%Y %H:%M:%S", 11283932Sbinkertn@umich.edu "%m/%d/%Y %H:%M", 11293932Sbinkertn@umich.edu "%m/%d/%Y", 11303932Sbinkertn@umich.edu "%m/%d/%y %H:%M:%S", 11313932Sbinkertn@umich.edu "%m/%d/%y %H:%M", 11323932Sbinkertn@umich.edu "%m/%d/%y"] 11333885Sbinkertn@umich.edu 11343932Sbinkertn@umich.edu 11353932Sbinkertn@umich.edudef parse_time(value): 11363885Sbinkertn@umich.edu from time import gmtime, strptime, struct_time, time 11373932Sbinkertn@umich.edu from datetime import datetime, date 11383932Sbinkertn@umich.edu 11393932Sbinkertn@umich.edu if isinstance(value, struct_time): 11403932Sbinkertn@umich.edu return value 11413932Sbinkertn@umich.edu 11423932Sbinkertn@umich.edu if isinstance(value, (int, long)): 11433932Sbinkertn@umich.edu return gmtime(value) 11443932Sbinkertn@umich.edu 11453932Sbinkertn@umich.edu if isinstance(value, (datetime, date)): 11463932Sbinkertn@umich.edu return value.timetuple() 11473932Sbinkertn@umich.edu 11483932Sbinkertn@umich.edu if isinstance(value, str): 11493932Sbinkertn@umich.edu if value in ('Now', 'Today'): 11503932Sbinkertn@umich.edu return time.gmtime(time.time()) 11513932Sbinkertn@umich.edu 11523932Sbinkertn@umich.edu for format in time_formats: 11533932Sbinkertn@umich.edu try: 11543932Sbinkertn@umich.edu return strptime(value, format) 11553885Sbinkertn@umich.edu except ValueError: 11563885Sbinkertn@umich.edu pass 11573885Sbinkertn@umich.edu 11583885Sbinkertn@umich.edu raise ValueError, "Could not parse '%s' as a time" % value 11594762Snate@binkert.org 11607673Snate@binkert.orgclass Time(ParamValue): 11617673Snate@binkert.org cxx_type = 'tm' 11627673Snate@binkert.org 11637673Snate@binkert.org @classmethod 11647673Snate@binkert.org def cxx_predecls(cls, code): 11653885Sbinkertn@umich.edu code('#include <time.h>') 11663932Sbinkertn@umich.edu 11673885Sbinkertn@umich.edu def __init__(self, value): 116810267SGeoffrey.Blake@arm.com self.value = parse_time(value) 116910267SGeoffrey.Blake@arm.com 117010267SGeoffrey.Blake@arm.com def __call__(self, value): 117110267SGeoffrey.Blake@arm.com self.__init__(value) 11724762Snate@binkert.org return value 117311988Sandreas.sandberg@arm.com 117411988Sandreas.sandberg@arm.com def getValue(self): 11754762Snate@binkert.org from _m5.core import tm 117611988Sandreas.sandberg@arm.com import calendar 11774762Snate@binkert.org 11783885Sbinkertn@umich.edu return tm.gmtime(calendar.timegm(self.value)) 11794762Snate@binkert.org 11803885Sbinkertn@umich.edu def __str__(self): 11813885Sbinkertn@umich.edu return time.asctime(self.value) 11823932Sbinkertn@umich.edu 11833885Sbinkertn@umich.edu def ini_str(self): 11848664SAli.Saidi@ARM.com return str(self) 118510380SAndrew.Bardsley@arm.com 11868664SAli.Saidi@ARM.com def get_config_as_dict(self): 11878664SAli.Saidi@ARM.com assert false 118810458Sandreas.hansson@arm.com return str(self) 118910458Sandreas.hansson@arm.com 119010458Sandreas.hansson@arm.com @classmethod 119110458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 119210458Sandreas.hansson@arm.com code('#include <time.h>') 119310458Sandreas.hansson@arm.com 119410458Sandreas.hansson@arm.com @classmethod 119510458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 119610458Sandreas.hansson@arm.com code('char *_parse_ret = strptime((${src}).c_str(),') 119710458Sandreas.hansson@arm.com code(' "%a %b %d %H:%M:%S %Y", &(${dest}));') 11983101Sstever@eecs.umich.edu code('${ret} _parse_ret && *_parse_ret == \'\\0\';'); 11993101Sstever@eecs.umich.edu 12003101Sstever@eecs.umich.edu# Enumerated types are a little more complex. The user specifies the 12013101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of 12023101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so). (In the 12033101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index 12043101Sstever@eecs.umich.edu# or the corresponding dictionary value. For now, since we only check 12053101Sstever@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file, 12063101Sstever@eecs.umich.edu# there's not much point in using the dictionary.) 12073101Sstever@eecs.umich.edu 12083101Sstever@eecs.umich.edu# What Enum() must do is generate a new type encapsulating the 12093101Sstever@eecs.umich.edu# provided list/dictionary so that specific values of the parameter 12103101Sstever@eecs.umich.edu# can be instances of that type. We define two hidden internal 12113101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then 12124762Snate@binkert.org# derive the new type from the appropriate base class on the fly. 12133101Sstever@eecs.umich.edu 12145033Smilesck@eecs.umich.eduallEnums = {} 12154762Snate@binkert.org# Metaclass for Enum types 12164762Snate@binkert.orgclass MetaEnum(MetaParamValue): 12174762Snate@binkert.org def __new__(mcls, name, bases, dict): 12184762Snate@binkert.org assert name not in allEnums 12194762Snate@binkert.org 12204762Snate@binkert.org cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 12214762Snate@binkert.org allEnums[name] = cls 12223101Sstever@eecs.umich.edu return cls 12233101Sstever@eecs.umich.edu 12243101Sstever@eecs.umich.edu def __init__(cls, name, bases, init_dict): 12253101Sstever@eecs.umich.edu if init_dict.has_key('map'): 12263101Sstever@eecs.umich.edu if not isinstance(cls.map, dict): 12273101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'map' " \ 12283101Sstever@eecs.umich.edu "must be of type dict" 12293101Sstever@eecs.umich.edu # build list of value strings from map 12303101Sstever@eecs.umich.edu cls.vals = cls.map.keys() 12313101Sstever@eecs.umich.edu cls.vals.sort() 12323101Sstever@eecs.umich.edu elif init_dict.has_key('vals'): 12333101Sstever@eecs.umich.edu if not isinstance(cls.vals, list): 12343101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'vals' " \ 12353101Sstever@eecs.umich.edu "must be of type list" 12363101Sstever@eecs.umich.edu # build string->value map from vals sequence 12373101Sstever@eecs.umich.edu cls.map = {} 12383101Sstever@eecs.umich.edu for idx,val in enumerate(cls.vals): 12393101Sstever@eecs.umich.edu cls.map[val] = idx 12403101Sstever@eecs.umich.edu else: 12413101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class must define "\ 12424762Snate@binkert.org "attribute 'map' or 'vals'" 12433101Sstever@eecs.umich.edu 12443101Sstever@eecs.umich.edu cls.cxx_type = 'Enums::%s' % name 12453101Sstever@eecs.umich.edu 12463101Sstever@eecs.umich.edu super(MetaEnum, cls).__init__(name, bases, init_dict) 12473101Sstever@eecs.umich.edu 12483101Sstever@eecs.umich.edu # Generate C++ class declaration for this enum type. 12497673Snate@binkert.org # Note that we wrap the enum in a class/struct to act as a namespace, 125010201SAndrew.Bardsley@arm.com # so that the enum strings can be brief w/o worrying about collisions. 125110201SAndrew.Bardsley@arm.com def cxx_decl(cls, code): 125210201SAndrew.Bardsley@arm.com wrapper_name = cls.wrapper_name 125310201SAndrew.Bardsley@arm.com wrapper = 'struct' if cls.wrapper_is_struct else 'namespace' 125410201SAndrew.Bardsley@arm.com name = cls.__name__ if cls.enum_name is None else cls.enum_name 12557673Snate@binkert.org idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name) 125610201SAndrew.Bardsley@arm.com 125710201SAndrew.Bardsley@arm.com code('''\ 12587673Snate@binkert.org#ifndef $idem_macro 125910201SAndrew.Bardsley@arm.com#define $idem_macro 12607673Snate@binkert.org 12617673Snate@binkert.org$wrapper $wrapper_name { 12627673Snate@binkert.org enum $name { 12634762Snate@binkert.org''') 12647673Snate@binkert.org code.indent(2) 12658902Sandreas.hansson@arm.com for val in cls.vals: 12667673Snate@binkert.org code('$val = ${{cls.map[val]}},') 126710201SAndrew.Bardsley@arm.com code('Num_$name = ${{len(cls.vals)}}') 12684762Snate@binkert.org code.dedent(2) 126910201SAndrew.Bardsley@arm.com code(' };') 127010201SAndrew.Bardsley@arm.com 127110201SAndrew.Bardsley@arm.com if cls.wrapper_is_struct: 127210201SAndrew.Bardsley@arm.com code(' static const char *${name}Strings[Num_${name}];') 127310201SAndrew.Bardsley@arm.com code('};') 127410201SAndrew.Bardsley@arm.com else: 127510201SAndrew.Bardsley@arm.com code('extern const char *${name}Strings[Num_${name}];') 127610201SAndrew.Bardsley@arm.com code('}') 127710201SAndrew.Bardsley@arm.com 12787673Snate@binkert.org code() 12797673Snate@binkert.org code('#endif // $idem_macro') 128010201SAndrew.Bardsley@arm.com 128110201SAndrew.Bardsley@arm.com def cxx_def(cls, code): 128210201SAndrew.Bardsley@arm.com wrapper_name = cls.wrapper_name 128310201SAndrew.Bardsley@arm.com file_name = cls.__name__ 128410201SAndrew.Bardsley@arm.com name = cls.__name__ if cls.enum_name is None else cls.enum_name 128510201SAndrew.Bardsley@arm.com 128610201SAndrew.Bardsley@arm.com code('#include "enums/$file_name.hh"') 128710201SAndrew.Bardsley@arm.com if cls.wrapper_is_struct: 128810201SAndrew.Bardsley@arm.com code('const char *${wrapper_name}::${name}Strings' 128910201SAndrew.Bardsley@arm.com '[Num_${name}] =') 129010201SAndrew.Bardsley@arm.com else: 129110201SAndrew.Bardsley@arm.com code('namespace Enums {') 129210201SAndrew.Bardsley@arm.com code.indent(1) 129310201SAndrew.Bardsley@arm.com code(' const char *${name}Strings[Num_${name}] =') 129410201SAndrew.Bardsley@arm.com 12954762Snate@binkert.org code('{') 12967673Snate@binkert.org code.indent(1) 129710201SAndrew.Bardsley@arm.com for val in cls.vals: 129810201SAndrew.Bardsley@arm.com code('"$val",') 129910201SAndrew.Bardsley@arm.com code.dedent(1) 130010201SAndrew.Bardsley@arm.com code('};') 130110201SAndrew.Bardsley@arm.com 130210201SAndrew.Bardsley@arm.com if not cls.wrapper_is_struct: 13033101Sstever@eecs.umich.edu code('} // namespace $wrapper_name') 130411988Sandreas.sandberg@arm.com code.dedent(1) 130511988Sandreas.sandberg@arm.com 130611988Sandreas.sandberg@arm.com def pybind_def(cls, code): 130711988Sandreas.sandberg@arm.com name = cls.__name__ 130811988Sandreas.sandberg@arm.com wrapper_name = cls.wrapper_name 130911988Sandreas.sandberg@arm.com enum_name = cls.__name__ if cls.enum_name is None else cls.enum_name 131011988Sandreas.sandberg@arm.com 131111988Sandreas.sandberg@arm.com code('''#include "pybind11/pybind11.h" 131211988Sandreas.sandberg@arm.com#include "pybind11/stl.h" 131311988Sandreas.sandberg@arm.com 131411988Sandreas.sandberg@arm.com#include <sim/init.hh> 131511988Sandreas.sandberg@arm.com 131611988Sandreas.sandberg@arm.comnamespace py = pybind11; 131711988Sandreas.sandberg@arm.com 131811988Sandreas.sandberg@arm.comstatic void 131911988Sandreas.sandberg@arm.commodule_init(py::module &m_internal) 132011988Sandreas.sandberg@arm.com{ 132111988Sandreas.sandberg@arm.com py::module m = m_internal.def_submodule("enum_${name}"); 132211988Sandreas.sandberg@arm.com 132311988Sandreas.sandberg@arm.com py::enum_<${wrapper_name}::${enum_name}>(m, "enum_${name}") 132411988Sandreas.sandberg@arm.com''') 132511988Sandreas.sandberg@arm.com 132611988Sandreas.sandberg@arm.com code.indent() 132711988Sandreas.sandberg@arm.com code.indent() 132811988Sandreas.sandberg@arm.com for val in cls.vals: 132911988Sandreas.sandberg@arm.com code('.value("${val}", ${wrapper_name}::${val})') 133011988Sandreas.sandberg@arm.com code('.value("Num_${name}", ${wrapper_name}::Num_${enum_name})') 133111988Sandreas.sandberg@arm.com code('.export_values()') 133211988Sandreas.sandberg@arm.com code(';') 133311988Sandreas.sandberg@arm.com code.dedent() 133411988Sandreas.sandberg@arm.com 133511988Sandreas.sandberg@arm.com code('}') 133611988Sandreas.sandberg@arm.com code.dedent() 133711988Sandreas.sandberg@arm.com code() 13388596Ssteve.reinhardt@amd.com code('static EmbeddedPyBind embed_enum("enum_${name}", module_init);') 13393101Sstever@eecs.umich.edu 13403101Sstever@eecs.umich.edu 13413101Sstever@eecs.umich.edu# Base class for enum types. 13423101Sstever@eecs.umich.educlass Enum(ParamValue): 134310267SGeoffrey.Blake@arm.com __metaclass__ = MetaEnum 13443101Sstever@eecs.umich.edu vals = [] 134510201SAndrew.Bardsley@arm.com cmd_line_settable = True 134610201SAndrew.Bardsley@arm.com 134710201SAndrew.Bardsley@arm.com # The name of the wrapping namespace or struct 134810201SAndrew.Bardsley@arm.com wrapper_name = 'Enums' 134910201SAndrew.Bardsley@arm.com 135010201SAndrew.Bardsley@arm.com # If true, the enum is wrapped in a struct rather than a namespace 135110201SAndrew.Bardsley@arm.com wrapper_is_struct = False 135210201SAndrew.Bardsley@arm.com 135310201SAndrew.Bardsley@arm.com # If not None, use this as the enum name rather than this class name 13543101Sstever@eecs.umich.edu enum_name = None 13553101Sstever@eecs.umich.edu 13563101Sstever@eecs.umich.edu def __init__(self, value): 13573101Sstever@eecs.umich.edu if value not in self.map: 13583101Sstever@eecs.umich.edu raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 13593101Sstever@eecs.umich.edu % (value, self.vals) 136010267SGeoffrey.Blake@arm.com self.value = value 136110267SGeoffrey.Blake@arm.com 136210267SGeoffrey.Blake@arm.com def __call__(self, value): 136310267SGeoffrey.Blake@arm.com self.__init__(value) 13647675Snate@binkert.org return value 13657675Snate@binkert.org 13667675Snate@binkert.org @classmethod 13677675Snate@binkert.org def cxx_predecls(cls, code): 13687675Snate@binkert.org code('#include "enums/$0.hh"', cls.__name__) 136910458Sandreas.hansson@arm.com 137010458Sandreas.hansson@arm.com @classmethod 137110458Sandreas.hansson@arm.com def cxx_ini_parse(cls, code, src, dest, ret): 137210458Sandreas.hansson@arm.com code('if (false) {') 137310458Sandreas.hansson@arm.com for elem_name in cls.map.iterkeys(): 137410458Sandreas.hansson@arm.com code('} else if (%s == "%s") {' % (src, elem_name)) 137510458Sandreas.hansson@arm.com code.indent() 137610458Sandreas.hansson@arm.com code('%s = Enums::%s;' % (dest, elem_name)) 137710458Sandreas.hansson@arm.com code('%s true;' % ret) 137810458Sandreas.hansson@arm.com code.dedent() 137910458Sandreas.hansson@arm.com code('} else {') 138010458Sandreas.hansson@arm.com code(' %s false;' % ret) 13814762Snate@binkert.org code('}') 138211988Sandreas.sandberg@arm.com 138311988Sandreas.sandberg@arm.com def getValue(self): 138411988Sandreas.sandberg@arm.com import m5.internal.params 13854762Snate@binkert.org e = getattr(m5.internal.params, "enum_%s" % self.__class__.__name__) 13863101Sstever@eecs.umich.edu return e(self.map[self.value]) 13873101Sstever@eecs.umich.edu 13883101Sstever@eecs.umich.edu def __str__(self): 13893101Sstever@eecs.umich.edu return self.value 13903101Sstever@eecs.umich.edu 13913101Sstever@eecs.umich.edu# how big does a rounding error need to be before we warn about it? 13924167Sbinkertn@umich.edufrequency_tolerance = 0.001 # 0.1% 13933101Sstever@eecs.umich.edu 139410267SGeoffrey.Blake@arm.comclass TickParamValue(NumericParamValue): 139510267SGeoffrey.Blake@arm.com cxx_type = 'Tick' 13967673Snate@binkert.org ex_str = "1MHz" 13977673Snate@binkert.org cmd_line_settable = True 13987673Snate@binkert.org 13997673Snate@binkert.org @classmethod 14007673Snate@binkert.org def cxx_predecls(cls, code): 140110267SGeoffrey.Blake@arm.com code('#include "base/types.hh"') 140210267SGeoffrey.Blake@arm.com 140310267SGeoffrey.Blake@arm.com def __call__(self, value): 140410267SGeoffrey.Blake@arm.com self.__init__(value) 14054762Snate@binkert.org return value 14064762Snate@binkert.org 14074762Snate@binkert.org def getValue(self): 140810458Sandreas.hansson@arm.com return long(self.value) 140910458Sandreas.hansson@arm.com 141010458Sandreas.hansson@arm.com @classmethod 141110458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 141210458Sandreas.hansson@arm.com code('#include <sstream>') 141310458Sandreas.hansson@arm.com 141410458Sandreas.hansson@arm.com # Ticks are expressed in seconds in JSON files and in plain 141510458Sandreas.hansson@arm.com # Ticks in .ini files. Switch based on a config flag 141610458Sandreas.hansson@arm.com @classmethod 141710458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 14184167Sbinkertn@umich.edu code('${ret} to_number(${src}, ${dest});') 141910267SGeoffrey.Blake@arm.com 142010267SGeoffrey.Blake@arm.comclass Latency(TickParamValue): 14213101Sstever@eecs.umich.edu ex_str = "100ns" 14224167Sbinkertn@umich.edu 14234167Sbinkertn@umich.edu def __init__(self, value): 14244167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 14254167Sbinkertn@umich.edu self.ticks = value.ticks 14264167Sbinkertn@umich.edu self.value = value.value 14274167Sbinkertn@umich.edu elif isinstance(value, Frequency): 14284167Sbinkertn@umich.edu self.ticks = value.ticks 14294167Sbinkertn@umich.edu self.value = 1.0 / value.value 14304167Sbinkertn@umich.edu elif value.endswith('t'): 14314167Sbinkertn@umich.edu self.ticks = True 14324167Sbinkertn@umich.edu self.value = int(value[:-1]) 14334167Sbinkertn@umich.edu else: 14343101Sstever@eecs.umich.edu self.ticks = False 143510267SGeoffrey.Blake@arm.com self.value = convert.toLatency(value) 143610267SGeoffrey.Blake@arm.com 143710267SGeoffrey.Blake@arm.com def __call__(self, value): 143810267SGeoffrey.Blake@arm.com self.__init__(value) 14393101Sstever@eecs.umich.edu return value 14403101Sstever@eecs.umich.edu 14413101Sstever@eecs.umich.edu def __getattr__(self, attr): 14423101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 14433101Sstever@eecs.umich.edu return self 14443101Sstever@eecs.umich.edu if attr == 'frequency': 14453101Sstever@eecs.umich.edu return Frequency(self) 14464762Snate@binkert.org raise AttributeError, "Latency object has no attribute '%s'" % attr 14474762Snate@binkert.org 14484762Snate@binkert.org def getValue(self): 14494762Snate@binkert.org if self.ticks or self.value == 0: 14504762Snate@binkert.org value = self.value 14514762Snate@binkert.org else: 14524762Snate@binkert.org value = ticks.fromSeconds(self.value) 145310380SAndrew.Bardsley@arm.com return long(value) 145410380SAndrew.Bardsley@arm.com 145510380SAndrew.Bardsley@arm.com def config_value(self): 14563101Sstever@eecs.umich.edu return self.getValue() 14573101Sstever@eecs.umich.edu 14584762Snate@binkert.org # convert latency to ticks 14593101Sstever@eecs.umich.edu def ini_str(self): 14604167Sbinkertn@umich.edu return '%d' % self.getValue() 146110267SGeoffrey.Blake@arm.com 146210267SGeoffrey.Blake@arm.comclass Frequency(TickParamValue): 14633101Sstever@eecs.umich.edu ex_str = "1GHz" 14644167Sbinkertn@umich.edu 14654167Sbinkertn@umich.edu def __init__(self, value): 14664167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 14674167Sbinkertn@umich.edu if value.value == 0: 14684167Sbinkertn@umich.edu self.value = 0 14694167Sbinkertn@umich.edu else: 14704167Sbinkertn@umich.edu self.value = 1.0 / value.value 14714167Sbinkertn@umich.edu self.ticks = value.ticks 14724167Sbinkertn@umich.edu elif isinstance(value, Frequency): 14734167Sbinkertn@umich.edu self.value = value.value 14744167Sbinkertn@umich.edu self.ticks = value.ticks 14754167Sbinkertn@umich.edu else: 14763101Sstever@eecs.umich.edu self.ticks = False 147710267SGeoffrey.Blake@arm.com self.value = convert.toFrequency(value) 147810267SGeoffrey.Blake@arm.com 147910267SGeoffrey.Blake@arm.com def __call__(self, value): 148010267SGeoffrey.Blake@arm.com self.__init__(value) 14813101Sstever@eecs.umich.edu return value 14823101Sstever@eecs.umich.edu 14833101Sstever@eecs.umich.edu def __getattr__(self, attr): 14843101Sstever@eecs.umich.edu if attr == 'frequency': 14853101Sstever@eecs.umich.edu return self 14863101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 14873101Sstever@eecs.umich.edu return Latency(self) 14884167Sbinkertn@umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 14894762Snate@binkert.org 14904762Snate@binkert.org # convert latency to ticks 14914762Snate@binkert.org def getValue(self): 14924762Snate@binkert.org if self.ticks or self.value == 0: 14934762Snate@binkert.org value = self.value 14944762Snate@binkert.org else: 14954762Snate@binkert.org value = ticks.fromSeconds(1.0 / self.value) 149610380SAndrew.Bardsley@arm.com return long(value) 149710380SAndrew.Bardsley@arm.com 149810380SAndrew.Bardsley@arm.com def config_value(self): 14993101Sstever@eecs.umich.edu return self.getValue() 15004762Snate@binkert.org 15013101Sstever@eecs.umich.edu def ini_str(self): 150210019Sandreas.hansson@arm.com return '%d' % self.getValue() 150310019Sandreas.hansson@arm.com 150410019Sandreas.hansson@arm.com# A generic Frequency and/or Latency value. Value is stored as a 15053101Sstever@eecs.umich.edu# latency, just like Latency and Frequency. 15064167Sbinkertn@umich.educlass Clock(TickParamValue): 15074167Sbinkertn@umich.edu def __init__(self, value): 15084167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 15094167Sbinkertn@umich.edu self.ticks = value.ticks 15104167Sbinkertn@umich.edu self.value = value.value 15114167Sbinkertn@umich.edu elif isinstance(value, Frequency): 15124167Sbinkertn@umich.edu self.ticks = value.ticks 15134167Sbinkertn@umich.edu self.value = 1.0 / value.value 15144167Sbinkertn@umich.edu elif value.endswith('t'): 15154167Sbinkertn@umich.edu self.ticks = True 15164167Sbinkertn@umich.edu self.value = int(value[:-1]) 15174167Sbinkertn@umich.edu else: 15183101Sstever@eecs.umich.edu self.ticks = False 151910267SGeoffrey.Blake@arm.com self.value = convert.anyToLatency(value) 152010267SGeoffrey.Blake@arm.com 152110267SGeoffrey.Blake@arm.com def __call__(self, value): 152210267SGeoffrey.Blake@arm.com self.__init__(value) 152310267SGeoffrey.Blake@arm.com return value 152410267SGeoffrey.Blake@arm.com 152510267SGeoffrey.Blake@arm.com def __str__(self): 15263101Sstever@eecs.umich.edu return "%s" % Latency(self) 15273101Sstever@eecs.umich.edu 15283101Sstever@eecs.umich.edu def __getattr__(self, attr): 15293101Sstever@eecs.umich.edu if attr == 'frequency': 15303101Sstever@eecs.umich.edu return Frequency(self) 15313101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 15323101Sstever@eecs.umich.edu return Latency(self) 15334762Snate@binkert.org raise AttributeError, "Frequency object has no attribute '%s'" % attr 15344762Snate@binkert.org 15354762Snate@binkert.org def getValue(self): 153610380SAndrew.Bardsley@arm.com return self.period.getValue() 153710380SAndrew.Bardsley@arm.com 153810380SAndrew.Bardsley@arm.com def config_value(self): 15393101Sstever@eecs.umich.edu return self.period.config_value() 15403101Sstever@eecs.umich.edu 15413101Sstever@eecs.umich.edu def ini_str(self): 15429827Sakash.bagdia@arm.com return self.period.ini_str() 15439827Sakash.bagdia@arm.com 154410267SGeoffrey.Blake@arm.comclass Voltage(float,ParamValue): 154511498Sakash.bagdia@ARM.com cxx_type = 'double' 154610267SGeoffrey.Blake@arm.com ex_str = "1V" 15479827Sakash.bagdia@arm.com cmd_line_settable = True 15489827Sakash.bagdia@arm.com 15499827Sakash.bagdia@arm.com def __new__(cls, value): 15509827Sakash.bagdia@arm.com # convert to voltage 15519827Sakash.bagdia@arm.com val = convert.toVoltage(value) 155210267SGeoffrey.Blake@arm.com return super(cls, Voltage).__new__(cls, val) 155310267SGeoffrey.Blake@arm.com 155410267SGeoffrey.Blake@arm.com def __call__(self, value): 155510267SGeoffrey.Blake@arm.com val = convert.toVoltage(value) 155610267SGeoffrey.Blake@arm.com self.__init__(val) 15579827Sakash.bagdia@arm.com return value 155810267SGeoffrey.Blake@arm.com 15599827Sakash.bagdia@arm.com def __str__(self): 15609827Sakash.bagdia@arm.com return str(self.getValue()) 15619827Sakash.bagdia@arm.com 15629827Sakash.bagdia@arm.com def getValue(self): 15639827Sakash.bagdia@arm.com value = float(self) 15649827Sakash.bagdia@arm.com return value 15659827Sakash.bagdia@arm.com 15669827Sakash.bagdia@arm.com def ini_str(self): 156710458Sandreas.hansson@arm.com return '%f' % self.getValue() 156810458Sandreas.hansson@arm.com 156910458Sandreas.hansson@arm.com @classmethod 157010458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 157110458Sandreas.hansson@arm.com code('#include <sstream>') 157210458Sandreas.hansson@arm.com 157310458Sandreas.hansson@arm.com @classmethod 157410458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 157510427Sandreas.hansson@arm.com code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 157610427Sandreas.hansson@arm.com 157710427Sandreas.hansson@arm.comclass Current(float, ParamValue): 157810427Sandreas.hansson@arm.com cxx_type = 'double' 157910427Sandreas.hansson@arm.com ex_str = "1mA" 158010427Sandreas.hansson@arm.com cmd_line_settable = False 158110427Sandreas.hansson@arm.com 158210427Sandreas.hansson@arm.com def __new__(cls, value): 158310427Sandreas.hansson@arm.com # convert to current 158410427Sandreas.hansson@arm.com val = convert.toCurrent(value) 158510427Sandreas.hansson@arm.com return super(cls, Current).__new__(cls, val) 158610427Sandreas.hansson@arm.com 158710427Sandreas.hansson@arm.com def __call__(self, value): 158810427Sandreas.hansson@arm.com val = convert.toCurrent(value) 158910427Sandreas.hansson@arm.com self.__init__(val) 159010427Sandreas.hansson@arm.com return value 159110427Sandreas.hansson@arm.com 159210427Sandreas.hansson@arm.com def __str__(self): 159310427Sandreas.hansson@arm.com return str(self.getValue()) 159410427Sandreas.hansson@arm.com 159510427Sandreas.hansson@arm.com def getValue(self): 159610427Sandreas.hansson@arm.com value = float(self) 159710427Sandreas.hansson@arm.com return value 159810427Sandreas.hansson@arm.com 159910427Sandreas.hansson@arm.com def ini_str(self): 160010458Sandreas.hansson@arm.com return '%f' % self.getValue() 160110458Sandreas.hansson@arm.com 160210458Sandreas.hansson@arm.com @classmethod 160310458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 160410458Sandreas.hansson@arm.com code('#include <sstream>') 160510458Sandreas.hansson@arm.com 160610458Sandreas.hansson@arm.com @classmethod 160710458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 16083101Sstever@eecs.umich.edu code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 16093101Sstever@eecs.umich.edu 161010267SGeoffrey.Blake@arm.comclass NetworkBandwidth(float,ParamValue): 161110267SGeoffrey.Blake@arm.com cxx_type = 'float' 161210267SGeoffrey.Blake@arm.com ex_str = "1Gbps" 16133101Sstever@eecs.umich.edu cmd_line_settable = True 16144167Sbinkertn@umich.edu 16154167Sbinkertn@umich.edu def __new__(cls, value): 16163101Sstever@eecs.umich.edu # convert to bits per second 16173101Sstever@eecs.umich.edu val = convert.toNetworkBandwidth(value) 16183101Sstever@eecs.umich.edu return super(cls, NetworkBandwidth).__new__(cls, val) 16193101Sstever@eecs.umich.edu 16203101Sstever@eecs.umich.edu def __str__(self): 162110267SGeoffrey.Blake@arm.com return str(self.val) 162210267SGeoffrey.Blake@arm.com 162310267SGeoffrey.Blake@arm.com def __call__(self, value): 162410267SGeoffrey.Blake@arm.com val = convert.toNetworkBandwidth(value) 162510267SGeoffrey.Blake@arm.com self.__init__(val) 16264762Snate@binkert.org return value 16274167Sbinkertn@umich.edu 16284167Sbinkertn@umich.edu def getValue(self): 16294167Sbinkertn@umich.edu # convert to seconds per byte 16304762Snate@binkert.org value = 8.0 / float(self) 16314762Snate@binkert.org # convert to ticks per byte 16324762Snate@binkert.org value = ticks.fromSeconds(value) 16334762Snate@binkert.org return float(value) 16344762Snate@binkert.org 16353101Sstever@eecs.umich.edu def ini_str(self): 163610380SAndrew.Bardsley@arm.com return '%f' % self.getValue() 163710380SAndrew.Bardsley@arm.com 163810380SAndrew.Bardsley@arm.com def config_value(self): 163910458Sandreas.hansson@arm.com return '%f' % self.getValue() 164010458Sandreas.hansson@arm.com 164110458Sandreas.hansson@arm.com @classmethod 164210458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 164310458Sandreas.hansson@arm.com code('#include <sstream>') 164410458Sandreas.hansson@arm.com 164510458Sandreas.hansson@arm.com @classmethod 164610458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 16473101Sstever@eecs.umich.edu code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 16483101Sstever@eecs.umich.edu 164910267SGeoffrey.Blake@arm.comclass MemoryBandwidth(float,ParamValue): 165010267SGeoffrey.Blake@arm.com cxx_type = 'float' 165110267SGeoffrey.Blake@arm.com ex_str = "1GB/s" 16525469Snate@binkert.org cmd_line_settable = True 16537743Sgblack@eecs.umich.edu 16543102Sstever@eecs.umich.edu def __new__(cls, value): 16553101Sstever@eecs.umich.edu # convert to bytes per second 16563101Sstever@eecs.umich.edu val = convert.toMemoryBandwidth(value) 165710267SGeoffrey.Blake@arm.com return super(cls, MemoryBandwidth).__new__(cls, val) 165810267SGeoffrey.Blake@arm.com 165910267SGeoffrey.Blake@arm.com def __call__(self, value): 166010267SGeoffrey.Blake@arm.com val = convert.toMemoryBandwidth(value) 16613101Sstever@eecs.umich.edu self.__init__(val) 16624762Snate@binkert.org return value 16634167Sbinkertn@umich.edu 16645468Snate@binkert.org def getValue(self): 16655468Snate@binkert.org # convert to seconds per byte 16665468Snate@binkert.org value = float(self) 16674167Sbinkertn@umich.edu if value: 16684762Snate@binkert.org value = 1.0 / float(self) 16694762Snate@binkert.org # convert to ticks per byte 16704762Snate@binkert.org value = ticks.fromSeconds(value) 16714762Snate@binkert.org return float(value) 16724762Snate@binkert.org 16733101Sstever@eecs.umich.edu def ini_str(self): 167410380SAndrew.Bardsley@arm.com return '%f' % self.getValue() 167510380SAndrew.Bardsley@arm.com 167610380SAndrew.Bardsley@arm.com def config_value(self): 167710458Sandreas.hansson@arm.com return '%f' % self.getValue() 167810458Sandreas.hansson@arm.com 167910458Sandreas.hansson@arm.com @classmethod 168010458Sandreas.hansson@arm.com def cxx_ini_predecls(cls, code): 168110458Sandreas.hansson@arm.com code('#include <sstream>') 168210458Sandreas.hansson@arm.com 168310458Sandreas.hansson@arm.com @classmethod 168410458Sandreas.hansson@arm.com def cxx_ini_parse(self, code, src, dest, ret): 16853101Sstever@eecs.umich.edu code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 16863101Sstever@eecs.umich.edu 16873101Sstever@eecs.umich.edu# 16883101Sstever@eecs.umich.edu# "Constants"... handy aliases for various values. 16893102Sstever@eecs.umich.edu# 16903102Sstever@eecs.umich.edu 16913102Sstever@eecs.umich.edu# Special class for NULL pointers. Note the special check in 16923102Sstever@eecs.umich.edu# make_param_value() above that lets these be assigned where a 16933102Sstever@eecs.umich.edu# SimObject is required. 16943102Sstever@eecs.umich.edu# only one copy of a particular node 16953102Sstever@eecs.umich.educlass NullSimObject(object): 16963102Sstever@eecs.umich.edu __metaclass__ = Singleton 16973102Sstever@eecs.umich.edu 16983102Sstever@eecs.umich.edu def __call__(cls): 16993102Sstever@eecs.umich.edu return cls 17003102Sstever@eecs.umich.edu 17013102Sstever@eecs.umich.edu def _instantiate(self, parent = None, path = ''): 17023102Sstever@eecs.umich.edu pass 17033102Sstever@eecs.umich.edu 17043102Sstever@eecs.umich.edu def ini_str(self): 17053102Sstever@eecs.umich.edu return 'Null' 17063102Sstever@eecs.umich.edu 17073102Sstever@eecs.umich.edu def unproxy(self, base): 17083102Sstever@eecs.umich.edu return self 17093102Sstever@eecs.umich.edu 17104762Snate@binkert.org def set_path(self, parent, name): 17113102Sstever@eecs.umich.edu pass 17123102Sstever@eecs.umich.edu 17133102Sstever@eecs.umich.edu def set_parent(self, parent, name): 171410380SAndrew.Bardsley@arm.com pass 171510380SAndrew.Bardsley@arm.com 171610380SAndrew.Bardsley@arm.com def clear_parent(self, old_parent): 17174762Snate@binkert.org pass 17184762Snate@binkert.org 17194762Snate@binkert.org def descendants(self): 17203102Sstever@eecs.umich.edu return 17213102Sstever@eecs.umich.edu yield None 17223102Sstever@eecs.umich.edu 17233102Sstever@eecs.umich.edu def __str__(self): 17243102Sstever@eecs.umich.edu return 'Null' 17253102Sstever@eecs.umich.edu 17263101Sstever@eecs.umich.edu def config_value(self): 17273101Sstever@eecs.umich.edu return None 17283101Sstever@eecs.umich.edu 17293101Sstever@eecs.umich.edu def getValue(self): 17303101Sstever@eecs.umich.edu return None 17313101Sstever@eecs.umich.edu 17323101Sstever@eecs.umich.edu# The only instance you'll ever need... 17333101Sstever@eecs.umich.eduNULL = NullSimObject() 17343101Sstever@eecs.umich.edu 17353101Sstever@eecs.umich.edudef isNullPointer(value): 17363101Sstever@eecs.umich.edu return isinstance(value, NullSimObject) 17373101Sstever@eecs.umich.edu 17383101Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound. 17393101Sstever@eecs.umich.eduMaxAddr = Addr.max 17403101Sstever@eecs.umich.eduMaxTick = Tick.max 17413101Sstever@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr) 17423101Sstever@eecs.umich.edu 17438839Sandreas.hansson@arm.com 17443105Sstever@eecs.umich.edu##################################################################### 17453101Sstever@eecs.umich.edu# 17463101Sstever@eecs.umich.edu# Port objects 17478839Sandreas.hansson@arm.com# 17483101Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system. 17493101Sstever@eecs.umich.edu# 17503105Sstever@eecs.umich.edu##################################################################### 17513101Sstever@eecs.umich.edu 17523103Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a 17533105Sstever@eecs.umich.edu# particular SimObject. 17543103Sstever@eecs.umich.educlass PortRef(object): 17558840Sandreas.hansson@arm.com def __init__(self, simobj, name, role): 17568840Sandreas.hansson@arm.com assert(isSimObject(simobj) or isSimObjectClass(simobj)) 17578840Sandreas.hansson@arm.com self.simobj = simobj 17588840Sandreas.hansson@arm.com self.name = name 17598840Sandreas.hansson@arm.com self.role = role 17603105Sstever@eecs.umich.edu self.peer = None # not associated with another port yet 17613105Sstever@eecs.umich.edu self.ccConnected = False # C++ port connection done? 17623105Sstever@eecs.umich.edu self.index = -1 # always -1 for non-vector ports 17633105Sstever@eecs.umich.edu 17649017Sandreas.hansson@arm.com def __str__(self): 17659017Sandreas.hansson@arm.com return '%s.%s' % (self.simobj, self.name) 17669017Sandreas.hansson@arm.com 17679017Sandreas.hansson@arm.com def __len__(self): 17683105Sstever@eecs.umich.edu # Return the number of connected ports, i.e. 0 is we have no 17693105Sstever@eecs.umich.edu # peer and 1 if we do. 17703105Sstever@eecs.umich.edu return int(self.peer != None) 17713105Sstever@eecs.umich.edu 17723105Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 17733105Sstever@eecs.umich.edu def ini_str(self): 17743105Sstever@eecs.umich.edu return str(self.peer) 17753105Sstever@eecs.umich.edu 17763105Sstever@eecs.umich.edu # for config.json 17773109Sstever@eecs.umich.edu def get_config_as_dict(self): 17783105Sstever@eecs.umich.edu return {'role' : self.role, 'peer' : str(self.peer)} 17793105Sstever@eecs.umich.edu 17803105Sstever@eecs.umich.edu def __getattr__(self, attr): 17813105Sstever@eecs.umich.edu if attr == 'peerObj': 17823105Sstever@eecs.umich.edu # shorthand for proxies 17833105Sstever@eecs.umich.edu return self.peer.simobj 17849014Sandreas.hansson@arm.com raise AttributeError, "'%s' object has no attribute '%s'" % \ 17859014Sandreas.hansson@arm.com (self.__class__.__name__, attr) 17863101Sstever@eecs.umich.edu 17873109Sstever@eecs.umich.edu # Full connection is symmetric (both ways). Called via 17883109Sstever@eecs.umich.edu # SimObject.__setattr__ as a result of a port assignment, e.g., 17893109Sstever@eecs.umich.edu # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 17903109Sstever@eecs.umich.edu # e.g., "obj1.portA[3] = obj2.portB". 17913109Sstever@eecs.umich.edu def connect(self, other): 17923109Sstever@eecs.umich.edu if isinstance(other, VectorPortRef): 17933109Sstever@eecs.umich.edu # reference to plain VectorPort is implicit append 17943109Sstever@eecs.umich.edu other = other._get_next() 17953109Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 17963101Sstever@eecs.umich.edu fatal("Port %s is already connected to %s, cannot connect %s\n", 179710355SGeoffrey.Blake@arm.com self, self.peer, other); 179810355SGeoffrey.Blake@arm.com self.peer = other 179910355SGeoffrey.Blake@arm.com if proxy.isproxy(other): 180010355SGeoffrey.Blake@arm.com other.set_param_desc(PortParamDesc()) 180110355SGeoffrey.Blake@arm.com elif isinstance(other, PortRef): 180210355SGeoffrey.Blake@arm.com if other.peer is not self: 180310355SGeoffrey.Blake@arm.com other.connect(self) 180410355SGeoffrey.Blake@arm.com else: 180510355SGeoffrey.Blake@arm.com raise TypeError, \ 180610355SGeoffrey.Blake@arm.com "assigning non-port reference '%s' to port '%s'" \ 180710355SGeoffrey.Blake@arm.com % (other, self) 180810355SGeoffrey.Blake@arm.com 180910355SGeoffrey.Blake@arm.com # Allow a master/slave port pair to be spliced between 181010355SGeoffrey.Blake@arm.com # a port and its connected peer. Useful operation for connecting 181110355SGeoffrey.Blake@arm.com # instrumentation structures into a system when it is necessary 181210355SGeoffrey.Blake@arm.com # to connect the instrumentation after the full system has been 181310355SGeoffrey.Blake@arm.com # constructed. 181410355SGeoffrey.Blake@arm.com def splice(self, new_master_peer, new_slave_peer): 181510355SGeoffrey.Blake@arm.com if self.peer and not proxy.isproxy(self.peer): 181610355SGeoffrey.Blake@arm.com if isinstance(new_master_peer, PortRef) and \ 181710355SGeoffrey.Blake@arm.com isinstance(new_slave_peer, PortRef): 181810355SGeoffrey.Blake@arm.com old_peer = self.peer 181910355SGeoffrey.Blake@arm.com if self.role == 'SLAVE': 182010355SGeoffrey.Blake@arm.com self.peer = new_master_peer 182110355SGeoffrey.Blake@arm.com old_peer.peer = new_slave_peer 182210355SGeoffrey.Blake@arm.com new_master_peer.connect(self) 182310355SGeoffrey.Blake@arm.com new_slave_peer.connect(old_peer) 182410355SGeoffrey.Blake@arm.com elif self.role == 'MASTER': 182510355SGeoffrey.Blake@arm.com self.peer = new_slave_peer 182610355SGeoffrey.Blake@arm.com old_peer.peer = new_master_peer 18273105Sstever@eecs.umich.edu new_slave_peer.connect(self) 18283105Sstever@eecs.umich.edu new_master_peer.connect(old_peer) 18293105Sstever@eecs.umich.edu else: 18303101Sstever@eecs.umich.edu panic("Port %s has unknown role, "+\ 18313105Sstever@eecs.umich.edu "cannot splice in new peers\n", self) 18323105Sstever@eecs.umich.edu else: 18333101Sstever@eecs.umich.edu raise TypeError, \ 18343105Sstever@eecs.umich.edu "Splicing non-port references '%s','%s' to port '%s'"\ 18353179Sstever@eecs.umich.edu % (new_peer, peers_new_peer, self) 18363105Sstever@eecs.umich.edu else: 18373105Sstever@eecs.umich.edu fatal("Port %s not connected, cannot splice in new peers\n", self) 18383101Sstever@eecs.umich.edu 18393101Sstever@eecs.umich.edu def clone(self, simobj, memo): 18403105Sstever@eecs.umich.edu if memo.has_key(self): 18413105Sstever@eecs.umich.edu return memo[self] 18423105Sstever@eecs.umich.edu newRef = copy.copy(self) 18433105Sstever@eecs.umich.edu memo[self] = newRef 18443105Sstever@eecs.umich.edu newRef.simobj = simobj 18453105Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 18463105Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 18473105Sstever@eecs.umich.edu peerObj = self.peer.simobj(_memo=memo) 18483105Sstever@eecs.umich.edu newRef.peer = self.peer.clone(peerObj, memo) 18493105Sstever@eecs.umich.edu assert(not isinstance(newRef.peer, VectorPortRef)) 18503105Sstever@eecs.umich.edu return newRef 18513101Sstever@eecs.umich.edu 18523101Sstever@eecs.umich.edu def unproxy(self, simobj): 185311802Sandreas.sandberg@arm.com assert(simobj is self.simobj) 18544762Snate@binkert.org if proxy.isproxy(self.peer): 18558839Sandreas.hansson@arm.com try: 18568839Sandreas.hansson@arm.com realPeer = self.peer.unproxy(self.simobj) 18578839Sandreas.hansson@arm.com except: 18588839Sandreas.hansson@arm.com print "Error in unproxying port '%s' of %s" % \ 18593101Sstever@eecs.umich.edu (self.name, self.simobj.path()) 18603101Sstever@eecs.umich.edu raise 18613101Sstever@eecs.umich.edu self.connect(realPeer) 18625578SSteve.Reinhardt@amd.com 18635578SSteve.Reinhardt@amd.com # Call C++ to create corresponding port connection between C++ objects 18648839Sandreas.hansson@arm.com def ccConnect(self): 18658839Sandreas.hansson@arm.com from _m5.pyobject import connectPorts 18668839Sandreas.hansson@arm.com 18678839Sandreas.hansson@arm.com if self.role == 'SLAVE': 18688839Sandreas.hansson@arm.com # do nothing and let the master take care of it 18698839Sandreas.hansson@arm.com return 18708839Sandreas.hansson@arm.com 18717526Ssteve.reinhardt@amd.com if self.ccConnected: # already done this 18728839Sandreas.hansson@arm.com return 18737526Ssteve.reinhardt@amd.com peer = self.peer 18747526Ssteve.reinhardt@amd.com if not self.peer: # nothing to connect to 18757526Ssteve.reinhardt@amd.com return 18767526Ssteve.reinhardt@amd.com 18777526Ssteve.reinhardt@amd.com # check that we connect a master to a slave 18787526Ssteve.reinhardt@amd.com if self.role == peer.role: 18797526Ssteve.reinhardt@amd.com raise TypeError, \ 18803101Sstever@eecs.umich.edu "cannot connect '%s' and '%s' due to identical role '%s'" \ 18813101Sstever@eecs.umich.edu % (peer, self, self.role) 18823101Sstever@eecs.umich.edu 18833105Sstever@eecs.umich.edu try: 18843105Sstever@eecs.umich.edu # self is always the master and peer the slave 18853105Sstever@eecs.umich.edu connectPorts(self.simobj.getCCObject(), self.name, self.index, 18868839Sandreas.hansson@arm.com peer.simobj.getCCObject(), peer.name, peer.index) 18878839Sandreas.hansson@arm.com except: 18883105Sstever@eecs.umich.edu print "Error connecting port %s.%s to %s.%s" % \ 18893105Sstever@eecs.umich.edu (self.simobj.path(), self.name, 18903105Sstever@eecs.umich.edu peer.simobj.path(), peer.name) 18913105Sstever@eecs.umich.edu raise 18923105Sstever@eecs.umich.edu self.ccConnected = True 18933105Sstever@eecs.umich.edu peer.ccConnected = True 18943105Sstever@eecs.umich.edu 18953105Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a 18968839Sandreas.hansson@arm.com# PortRef, but has an index. 18973105Sstever@eecs.umich.educlass VectorPortElementRef(PortRef): 18983105Sstever@eecs.umich.edu def __init__(self, simobj, name, role, index): 18993105Sstever@eecs.umich.edu PortRef.__init__(self, simobj, name, role) 19008839Sandreas.hansson@arm.com self.index = index 19013105Sstever@eecs.umich.edu 19023105Sstever@eecs.umich.edu def __str__(self): 19033109Sstever@eecs.umich.edu return '%s.%s[%d]' % (self.simobj, self.name, self.index) 19043109Sstever@eecs.umich.edu 19053109Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element). 19068840Sandreas.hansson@arm.com# Can be indexed to retrieve individual VectorPortElementRef instances. 19078840Sandreas.hansson@arm.comclass VectorPortRef(object): 19088840Sandreas.hansson@arm.com def __init__(self, simobj, name, role): 19098840Sandreas.hansson@arm.com assert(isSimObject(simobj) or isSimObjectClass(simobj)) 19108840Sandreas.hansson@arm.com self.simobj = simobj 19113105Sstever@eecs.umich.edu self.name = name 19123105Sstever@eecs.umich.edu self.role = role 19133105Sstever@eecs.umich.edu self.elements = [] 19143105Sstever@eecs.umich.edu 19159017Sandreas.hansson@arm.com def __str__(self): 19169017Sandreas.hansson@arm.com return '%s.%s[:]' % (self.simobj, self.name) 19179017Sandreas.hansson@arm.com 19189017Sandreas.hansson@arm.com def __len__(self): 19199017Sandreas.hansson@arm.com # Return the number of connected peers, corresponding the the 19203105Sstever@eecs.umich.edu # length of the elements. 19213105Sstever@eecs.umich.edu return len(self.elements) 19223105Sstever@eecs.umich.edu 19233105Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 19243105Sstever@eecs.umich.edu def ini_str(self): 19258839Sandreas.hansson@arm.com return ' '.join([el.ini_str() for el in self.elements]) 19263105Sstever@eecs.umich.edu 19273105Sstever@eecs.umich.edu # for config.json 19283105Sstever@eecs.umich.edu def get_config_as_dict(self): 19293105Sstever@eecs.umich.edu return {'role' : self.role, 19303105Sstever@eecs.umich.edu 'peer' : [el.ini_str() for el in self.elements]} 19313105Sstever@eecs.umich.edu 19323105Sstever@eecs.umich.edu def __getitem__(self, key): 19333105Sstever@eecs.umich.edu if not isinstance(key, int): 19343105Sstever@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 19353105Sstever@eecs.umich.edu if key >= len(self.elements): 19363105Sstever@eecs.umich.edu # need to extend list 19373105Sstever@eecs.umich.edu ext = [VectorPortElementRef(self.simobj, self.name, self.role, i) 19383105Sstever@eecs.umich.edu for i in range(len(self.elements), key+1)] 19393109Sstever@eecs.umich.edu self.elements.extend(ext) 19403109Sstever@eecs.umich.edu return self.elements[key] 19413109Sstever@eecs.umich.edu 19423109Sstever@eecs.umich.edu def _get_next(self): 19433109Sstever@eecs.umich.edu return self[len(self.elements)] 19443109Sstever@eecs.umich.edu 19453109Sstever@eecs.umich.edu def __setitem__(self, key, value): 19463109Sstever@eecs.umich.edu if not isinstance(key, int): 19473109Sstever@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 19483109Sstever@eecs.umich.edu self[key].connect(value) 19493109Sstever@eecs.umich.edu 19503109Sstever@eecs.umich.edu def connect(self, other): 19513109Sstever@eecs.umich.edu if isinstance(other, (list, tuple)): 19523109Sstever@eecs.umich.edu # Assign list of port refs to vector port. 19533109Sstever@eecs.umich.edu # For now, append them... not sure if that's the right semantics 19543109Sstever@eecs.umich.edu # or if it should replace the current vector. 19553109Sstever@eecs.umich.edu for ref in other: 19563109Sstever@eecs.umich.edu self._get_next().connect(ref) 19573109Sstever@eecs.umich.edu else: 19583105Sstever@eecs.umich.edu # scalar assignment to plain VectorPort is implicit append 19593105Sstever@eecs.umich.edu self._get_next().connect(other) 19603105Sstever@eecs.umich.edu 19613105Sstever@eecs.umich.edu def clone(self, simobj, memo): 19623105Sstever@eecs.umich.edu if memo.has_key(self): 19633105Sstever@eecs.umich.edu return memo[self] 19643105Sstever@eecs.umich.edu newRef = copy.copy(self) 19653101Sstever@eecs.umich.edu memo[self] = newRef 19663101Sstever@eecs.umich.edu newRef.simobj = simobj 19673101Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 19683101Sstever@eecs.umich.edu newRef.elements = [el.clone(simobj, memo) for el in self.elements] 19693101Sstever@eecs.umich.edu return newRef 19703101Sstever@eecs.umich.edu 19713105Sstever@eecs.umich.edu def unproxy(self, simobj): 19728839Sandreas.hansson@arm.com [el.unproxy(simobj) for el in self.elements] 19733101Sstever@eecs.umich.edu 19743101Sstever@eecs.umich.edu def ccConnect(self): 19753101Sstever@eecs.umich.edu [el.ccConnect() for el in self.elements] 19763105Sstever@eecs.umich.edu 19773105Sstever@eecs.umich.edu# Port description object. Like a ParamDesc object, this represents a 19783101Sstever@eecs.umich.edu# logical port in the SimObject class, not a particular port on a 19798840Sandreas.hansson@arm.com# SimObject instance. The latter are represented by PortRef objects. 19808840Sandreas.hansson@arm.comclass Port(object): 19818840Sandreas.hansson@arm.com # Generate a PortRef for this port on the given SimObject with the 19828840Sandreas.hansson@arm.com # given name 19838840Sandreas.hansson@arm.com def makeRef(self, simobj): 198411988Sandreas.sandberg@arm.com return PortRef(simobj, self.name, self.role) 198511988Sandreas.sandberg@arm.com 198611988Sandreas.sandberg@arm.com # Connect an instance of this port (on the given SimObject with 19878840Sandreas.hansson@arm.com # the given name) with the port described by the supplied PortRef 19888840Sandreas.hansson@arm.com def connect(self, simobj, ref): 19898840Sandreas.hansson@arm.com self.makeRef(simobj).connect(ref) 19908840Sandreas.hansson@arm.com 19918840Sandreas.hansson@arm.com # No need for any pre-declarations at the moment as we merely rely 19928840Sandreas.hansson@arm.com # on an unsigned int. 19938839Sandreas.hansson@arm.com def cxx_predecls(self, code): 19948839Sandreas.hansson@arm.com pass 19958839Sandreas.hansson@arm.com 19968839Sandreas.hansson@arm.com def pybind_predecls(self, code): 19978839Sandreas.hansson@arm.com cls.cxx_predecls(self, code) 19988839Sandreas.hansson@arm.com 19998839Sandreas.hansson@arm.com # Declare an unsigned int with the same name as the port, that 20008839Sandreas.hansson@arm.com # will eventually hold the number of connected ports (and thus the 20018839Sandreas.hansson@arm.com # number of elements for a VectorPort). 20028839Sandreas.hansson@arm.com def cxx_decl(self, code): 20038839Sandreas.hansson@arm.com code('unsigned int port_${{self.name}}_connection_count;') 20048839Sandreas.hansson@arm.com 20058839Sandreas.hansson@arm.comclass MasterPort(Port): 20068839Sandreas.hansson@arm.com # MasterPort("description") 20078839Sandreas.hansson@arm.com def __init__(self, *args): 20088839Sandreas.hansson@arm.com if len(args) == 1: 20098839Sandreas.hansson@arm.com self.desc = args[0] 20108839Sandreas.hansson@arm.com self.role = 'MASTER' 20113101Sstever@eecs.umich.edu else: 201210405Sandreas.hansson@arm.com raise TypeError, 'wrong number of arguments' 20133101Sstever@eecs.umich.edu 20143105Sstever@eecs.umich.educlass SlavePort(Port): 20153101Sstever@eecs.umich.edu # SlavePort("description") 20163101Sstever@eecs.umich.edu def __init__(self, *args): 20173105Sstever@eecs.umich.edu if len(args) == 1: 20188839Sandreas.hansson@arm.com self.desc = args[0] 20198839Sandreas.hansson@arm.com self.role = 'SLAVE' 20208839Sandreas.hansson@arm.com else: 20218839Sandreas.hansson@arm.com raise TypeError, 'wrong number of arguments' 20228839Sandreas.hansson@arm.com 20238839Sandreas.hansson@arm.com# VectorPort description object. Like Port, but represents a vector 20248839Sandreas.hansson@arm.com# of connections (e.g., as on a XBar). 20258839Sandreas.hansson@arm.comclass VectorPort(Port): 20268839Sandreas.hansson@arm.com def __init__(self, *args): 20278839Sandreas.hansson@arm.com self.isVec = True 20288839Sandreas.hansson@arm.com 20298839Sandreas.hansson@arm.com def makeRef(self, simobj): 20308839Sandreas.hansson@arm.com return VectorPortRef(simobj, self.name, self.role) 20318839Sandreas.hansson@arm.com 20328839Sandreas.hansson@arm.comclass VectorMasterPort(VectorPort): 20338839Sandreas.hansson@arm.com # VectorMasterPort("description") 20348839Sandreas.hansson@arm.com def __init__(self, *args): 20358839Sandreas.hansson@arm.com if len(args) == 1: 20368839Sandreas.hansson@arm.com self.desc = args[0] 20378839Sandreas.hansson@arm.com self.role = 'MASTER' 20388839Sandreas.hansson@arm.com VectorPort.__init__(self, *args) 20393105Sstever@eecs.umich.edu else: 20403109Sstever@eecs.umich.edu raise TypeError, 'wrong number of arguments' 20413109Sstever@eecs.umich.edu 20423109Sstever@eecs.umich.educlass VectorSlavePort(VectorPort): 20433109Sstever@eecs.umich.edu # VectorSlavePort("description") 20443109Sstever@eecs.umich.edu def __init__(self, *args): 20453109Sstever@eecs.umich.edu if len(args) == 1: 20463109Sstever@eecs.umich.edu self.desc = args[0] 20473109Sstever@eecs.umich.edu self.role = 'SLAVE' 20483105Sstever@eecs.umich.edu VectorPort.__init__(self, *args) 20496654Snate@binkert.org else: 20506654Snate@binkert.org raise TypeError, 'wrong number of arguments' 20516654Snate@binkert.org 20526654Snate@binkert.org# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 20536654Snate@binkert.org# proxy objects (via set_param_desc()) so that proxy error messages 20546654Snate@binkert.org# make sense. 20556654Snate@binkert.orgclass PortParamDesc(object): 20566654Snate@binkert.org __metaclass__ = Singleton 20576654Snate@binkert.org 20583101Sstever@eecs.umich.edu ptype_str = 'Port' 20593101Sstever@eecs.umich.edu ptype = Port 20603101Sstever@eecs.umich.edu 20613101Sstever@eecs.umich.edubaseEnums = allEnums.copy() 20623101Sstever@eecs.umich.edubaseParams = allParams.copy() 20633101Sstever@eecs.umich.edu 20647777Sgblack@eecs.umich.edudef clear(): 20653101Sstever@eecs.umich.edu global allEnums, allParams 20669827Sakash.bagdia@arm.com 20673101Sstever@eecs.umich.edu allEnums = baseEnums.copy() 20689232Sandreas.hansson@arm.com allParams = baseParams.copy() 20693101Sstever@eecs.umich.edu 20703885Sbinkertn@umich.edu__all__ = ['Param', 'VectorParam', 20713102Sstever@eecs.umich.edu 'Enum', 'Bool', 'String', 'Float', 20728839Sandreas.hansson@arm.com 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 20738839Sandreas.hansson@arm.com 'Int32', 'UInt32', 'Int64', 'UInt64', 20746654Snate@binkert.org 'Counter', 'Addr', 'Tick', 'Percent', 20756654Snate@binkert.org 'TcpPort', 'UdpPort', 'EthernetAddr', 2076 'IpAddress', 'IpNetmask', 'IpWithPort', 2077 'MemorySize', 'MemorySize32', 2078 'Latency', 'Frequency', 'Clock', 'Voltage', 2079 'NetworkBandwidth', 'MemoryBandwidth', 2080 'AddrRange', 2081 'MaxAddr', 'MaxTick', 'AllMemory', 2082 'Time', 2083 'NextEthernetAddr', 'NULL', 2084 'MasterPort', 'SlavePort', 2085 'VectorMasterPort', 'VectorSlavePort'] 2086 2087import SimObject 2088