proxy.py revision 13719
12137SN/A# Copyright (c) 2018 ARM Limited 25268Sksewell@umich.edu# All rights reserved. 35254Sksewell@umich.edu# 45254Sksewell@umich.edu# The license below extends only to copyright in the software and shall 52137SN/A# not be construed as granting a license to any other intellectual 65254Sksewell@umich.edu# property including but not limited to intellectual property relating 75254Sksewell@umich.edu# to a hardware implementation of the functionality of the software 85254Sksewell@umich.edu# licensed hereunder. You may use the software subject to the license 95254Sksewell@umich.edu# terms below provided that you ensure that this notice is replicated 105254Sksewell@umich.edu# unmodified and in its entirety in all distributions of the software, 115254Sksewell@umich.edu# modified or unmodified, in source code or in binary form. 125254Sksewell@umich.edu# 135254Sksewell@umich.edu# Copyright (c) 2004-2006 The Regents of The University of Michigan 145254Sksewell@umich.edu# All rights reserved. 155254Sksewell@umich.edu# 162137SN/A# Redistribution and use in source and binary forms, with or without 175254Sksewell@umich.edu# modification, are permitted provided that the following conditions are 185254Sksewell@umich.edu# met: redistributions of source code must retain the above copyright 195254Sksewell@umich.edu# notice, this list of conditions and the following disclaimer; 205254Sksewell@umich.edu# redistributions in binary form must reproduce the above copyright 215254Sksewell@umich.edu# notice, this list of conditions and the following disclaimer in the 225254Sksewell@umich.edu# documentation and/or other materials provided with the distribution; 235254Sksewell@umich.edu# neither the name of the copyright holders nor the names of its 245254Sksewell@umich.edu# contributors may be used to endorse or promote products derived from 255254Sksewell@umich.edu# this software without specific prior written permission. 265254Sksewell@umich.edu# 275254Sksewell@umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 282665Ssaidi@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 295268Sksewell@umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 305268Sksewell@umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 312137SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 322137SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3311793Sbrandon.potter@amd.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3411793Sbrandon.potter@amd.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3511793Sbrandon.potter@amd.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 362597SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3713985Sgabeblack@google.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 382137SN/A# 392680Sktlim@umich.edu# Authors: Steve Reinhardt 408232Snate@binkert.org# Nathan Binkert 412137SN/A 428229Snate@binkert.org##################################################################### 432137SN/A# 4411794Sbrandon.potter@amd.com# Proxy object support. 458229Snate@binkert.org# 464661Sksewell@umich.edu##################################################################### 472137SN/A 482137SN/Afrom __future__ import print_function 492137SN/Afrom __future__ import absolute_import 502137SN/Aimport six 5113985Sgabeblack@google.comif six.PY3: 5213985Sgabeblack@google.com long = int 5313985Sgabeblack@google.com 5413985Sgabeblack@google.comimport copy 5513985Sgabeblack@google.com 5613985Sgabeblack@google.com 5713985Sgabeblack@google.comclass BaseProxy(object): 5813985Sgabeblack@google.com def __init__(self, search_self, search_up): 5913985Sgabeblack@google.com self._search_self = search_self 6013985Sgabeblack@google.com self._search_up = search_up 6113985Sgabeblack@google.com self._multipliers = [] 6213985Sgabeblack@google.com 6313985Sgabeblack@google.com def __str__(self): 6413985Sgabeblack@google.com if self._search_self and not self._search_up: 6513985Sgabeblack@google.com s = 'Self' 6613985Sgabeblack@google.com elif not self._search_self and self._search_up: 6713985Sgabeblack@google.com s = 'Parent' 6813985Sgabeblack@google.com else: 6913985Sgabeblack@google.com s = 'ConfusedProxy' 7013985Sgabeblack@google.com return s + '.' + self.path() 7113985Sgabeblack@google.com 7213985Sgabeblack@google.com def __setattr__(self, attr, value): 7313985Sgabeblack@google.com if not attr.startswith('_'): 7413985Sgabeblack@google.com raise AttributeError( 7513985Sgabeblack@google.com "cannot set attribute '%s' on proxy object" % attr) 7613985Sgabeblack@google.com super(BaseProxy, self).__setattr__(attr, value) 7713985Sgabeblack@google.com 7813985Sgabeblack@google.com # support for multiplying proxies by constants or other proxies to 7913985Sgabeblack@google.com # other params 8013985Sgabeblack@google.com def __mul__(self, other): 812137SN/A if not (isinstance(other, (int, long, float)) or isproxy(other)): 822137SN/A raise TypeError( 8313995Sbrandon.potter@amd.com "Proxy multiplier must be a constant or a proxy to a param") 842137SN/A self._multipliers.append(other) 856701Sgblack@eecs.umich.edu return self 8613995Sbrandon.potter@amd.com 876701Sgblack@eecs.umich.edu __rmul__ = __mul__ 882137SN/A 892137SN/A def _mulcheck(self, result, base): 909149SAli.Saidi@ARM.com for multiplier in self._multipliers: 9114014Sciro.santilli@arm.com if isproxy(multiplier): 922137SN/A multiplier = multiplier.unproxy(base) 932137SN/A # assert that we are multiplying with a compatible 942137SN/A # param 9514024Sgabeblack@google.com if not isinstance(multiplier, params.NumericParamValue): 962137SN/A raise TypeError( 972137SN/A "Proxy multiplier must be a numerical param") 982137SN/A multiplier = multiplier.getValue() 992484SN/A result *= multiplier 1002137SN/A return result 1012137SN/A 1022137SN/A def unproxy(self, base): 10313995Sbrandon.potter@amd.com obj = base 1042137SN/A done = False 1056701Sgblack@eecs.umich.edu 10613995Sbrandon.potter@amd.com if self._search_self: 1076701Sgblack@eecs.umich.edu result, done = self.find(obj) 1086701Sgblack@eecs.umich.edu 1096701Sgblack@eecs.umich.edu if self._search_up: 1102137SN/A # Search up the tree but mark ourself 1112137SN/A # as visited to avoid a self-reference 1126378Sgblack@eecs.umich.edu self._visited = True 11311320Ssteve.reinhardt@amd.com obj._visited = True 1146378Sgblack@eecs.umich.edu while not done: 1156701Sgblack@eecs.umich.edu obj = obj._parent 1166378Sgblack@eecs.umich.edu if not obj: 1176378Sgblack@eecs.umich.edu break 11814024Sgabeblack@google.com result, done = self.find(obj) 1196378Sgblack@eecs.umich.edu 1206378Sgblack@eecs.umich.edu self._visited = False 1212137SN/A base._visited = False 1222484SN/A 1232137SN/A if not done: 1242137SN/A raise AttributeError( 1252137SN/A "Can't resolve proxy '%s' of type '%s' from '%s'" % \ 1262137SN/A (self.path(), self._pdesc.ptype_str, base.path())) 1272137SN/A 1282137SN/A if isinstance(result, BaseProxy): 1292137SN/A if result == self: 1302484SN/A raise RuntimeError("Cycle in unproxy") 1312137SN/A result = result.unproxy(obj) 13213995Sbrandon.potter@amd.com 1332137SN/A return self._mulcheck(result, base) 1346701Sgblack@eecs.umich.edu 13513995Sbrandon.potter@amd.com def getindex(obj, index): 1366701Sgblack@eecs.umich.edu if index == None: 1376701Sgblack@eecs.umich.edu return obj 1386701Sgblack@eecs.umich.edu try: 1392137SN/A obj = obj[index] 1402137SN/A except TypeError: 1412137SN/A if index != 0: 1426378Sgblack@eecs.umich.edu raise 1436378Sgblack@eecs.umich.edu # if index is 0 and item is not subscriptable, just 1446378Sgblack@eecs.umich.edu # use item itself (so cpu[0] works on uniprocessors) 1456701Sgblack@eecs.umich.edu return obj 1466378Sgblack@eecs.umich.edu getindex = staticmethod(getindex) 14714024Sgabeblack@google.com 1486378Sgblack@eecs.umich.edu # This method should be called once the proxy is assigned to a 1492137SN/A # particular parameter or port to set the expected type of the 1506378Sgblack@eecs.umich.edu # resolved proxy 1516378Sgblack@eecs.umich.edu def set_param_desc(self, pdesc): 1522137SN/A self._pdesc = pdesc 1532484SN/A 1542137SN/Aclass AttrProxy(BaseProxy): 1552137SN/A def __init__(self, search_self, search_up, attr): 1562137SN/A super(AttrProxy, self).__init__(search_self, search_up) 1572137SN/A self._attr = attr 1582137SN/A self._modifiers = [] 1592137SN/A 1602137SN/A def __getattr__(self, attr): 1616808Sgblack@eecs.umich.edu # python uses __bases__ internally for inheritance 16213995Sbrandon.potter@amd.com if attr.startswith('_'): 1636808Sgblack@eecs.umich.edu return super(AttrProxy, self).__getattr__(self, attr) 1646808Sgblack@eecs.umich.edu if hasattr(self, '_pdesc'): 16513995Sbrandon.potter@amd.com raise AttributeError("Attribute reference on bound proxy") 1666808Sgblack@eecs.umich.edu # Return a copy of self rather than modifying self in place 1676808Sgblack@eecs.umich.edu # since self could be an indirect reference via a variable or 1686808Sgblack@eecs.umich.edu # parameter 1696808Sgblack@eecs.umich.edu new_self = copy.deepcopy(self) 1706808Sgblack@eecs.umich.edu new_self._modifiers.append(attr) 1712137SN/A return new_self 1722484SN/A 1732137SN/A # support indexing on proxies (e.g., Self.cpu[0]) 1742137SN/A def __getitem__(self, key): 17513570Sbrandon.potter@amd.com if not isinstance(key, int): 17613570Sbrandon.potter@amd.com raise TypeError("Proxy object requires integer index") 1772553SN/A if hasattr(self, '_pdesc'): 1782137SN/A raise AttributeError("Index operation on bound proxy") 1792484SN/A new_self = copy.deepcopy(self) 1802484SN/A new_self._modifiers.append(key) 1812137SN/A return new_self 1822137SN/A 1832484SN/A def find(self, obj): 1842137SN/A try: 1852484SN/A val = getattr(obj, self._attr) 1862137SN/A visited = False 1872553SN/A if hasattr(val, '_visited'): 1882484SN/A visited = getattr(val, '_visited') 1895748SSteve.Reinhardt@amd.com 1902484SN/A if not visited: 1912137SN/A # for any additional unproxying to be done, pass the 1922484SN/A # current, rather than the original object so that proxy 1932484SN/A # has the right context 1942137SN/A obj = val 1952137SN/A else: 1962484SN/A return None, False 1972484SN/A except: 1982484SN/A return None, False 1992484SN/A while isproxy(val): 2002484SN/A val = val.unproxy(obj) 2012484SN/A for m in self._modifiers: 2022484SN/A if isinstance(m, str): 2032484SN/A val = getattr(val, m) 2042484SN/A elif isinstance(m, int): 2052137SN/A val = val[m] 2062484SN/A else: 2072484SN/A assert("Item must be string or integer") 2082137SN/A while isproxy(val): 2094661Sksewell@umich.edu val = val.unproxy(obj) 2102484SN/A return val, True 2115513SMichael.Adler@intel.com 2122484SN/A def path(self): 2132137SN/A p = self._attr 2144661Sksewell@umich.edu for m in self._modifiers: 2152484SN/A if isinstance(m, str): 2162484SN/A p += '.%s' % m 2175748SSteve.Reinhardt@amd.com elif isinstance(m, int): 2182491SN/A p += '[%d]' % m 2192484SN/A else: 2202484SN/A assert("Item must be string or integer") 2212491SN/A return p 2222491SN/A 2232137SN/Aclass AnyProxy(BaseProxy): 2242484SN/A def find(self, obj): 2252484SN/A return obj.find_any(self._pdesc.ptype) 2265867Sksewell@umich.edu 2272686Sksewell@umich.edu def path(self): 2282484SN/A return 'any' 2292484SN/A 2302484SN/A# The AllProxy traverses the entire sub-tree (not only the children) 2312484SN/A# and adds all objects of a specific type 2325513SMichael.Adler@intel.comclass AllProxy(BaseProxy): 2332137SN/A def find(self, obj): 2342484SN/A return obj.find_all(self._pdesc.ptype) 2352484SN/A 2362484SN/A def path(self): 2372484SN/A return 'all' 2382484SN/A 2392495SN/Adef isproxy(obj): 2402495SN/A from . import params 2412484SN/A if isinstance(obj, (BaseProxy, params.EthernetAddr)): 2422484SN/A return True 2432495SN/A elif isinstance(obj, (list, tuple)): 2442484SN/A for v in obj: 2452495SN/A if isproxy(v): 2462484SN/A return True 2476378Sgblack@eecs.umich.edu return False 2486378Sgblack@eecs.umich.edu 2494661Sksewell@umich.educlass ProxyFactory(object): 2502484SN/A def __init__(self, search_self, search_up): 2512484SN/A self.search_self = search_self 2522484SN/A self.search_up = search_up 2532484SN/A 2542484SN/A def __getattr__(self, attr): 2552484SN/A if attr == 'any': 2562484SN/A return AnyProxy(self.search_self, self.search_up) 2575513SMichael.Adler@intel.com elif attr == 'all': 2582484SN/A if self.search_up: 2592484SN/A assert("Parant.all is not supported") 2602484SN/A return AllProxy(self.search_self, self.search_up) 2612484SN/A else: 2622553SN/A return AttrProxy(self.search_self, self.search_up, attr) 2632495SN/A 2642686Sksewell@umich.edu# global objects for handling proxies 2652686Sksewell@umich.eduParent = ProxyFactory(search_self = False, search_up = True) 2664661Sksewell@umich.eduSelf = ProxyFactory(search_self = True, search_up = False) 2674661Sksewell@umich.edu 2682484SN/A# limit exports on 'from proxy import *' 2692484SN/A__all__ = ['Parent', 'Self'] 2702484SN/A