1# Copyright (c) 2004-2006 The Regents of The University of Michigan 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are 6# met: redistributions of source code must retain the above copyright 7# notice, this list of conditions and the following disclaimer; 8# redistributions in binary form must reproduce the above copyright --- 738 unchanged lines hidden (view full) --- 747# 748# Ports are used to interconnect objects in the memory system. 749# 750##################################################################### 751 752# Port reference: encapsulates a reference to a particular port on a 753# particular SimObject. 754class PortRef(object): |
755 def __init__(self, simobj, name): 756 assert(isSimObject(simobj) or isSimObjectClass(simobj)) |
757 self.simobj = simobj 758 self.name = name |
759 self.peer = None # not associated with another port yet 760 self.ccConnected = False # C++ port connection done? |
761 self.index = -1 # always -1 for non-vector ports |
762 763 def __str__(self): |
764 return '%s.%s' % (self.simobj, self.name) |
765 |
766 # for config.ini, print peer's name (not ours) 767 def ini_str(self): 768 return str(self.peer) 769 770 def __getattr__(self, attr): 771 if attr == 'peerObj': 772 # shorthand for proxies 773 return self.peer.simobj 774 raise AttributeError, "'%s' object has no attribute '%s'" % \ 775 (self.__class__.__name__, attr) 776 777 # Full connection is symmetric (both ways). Called via 778 # SimObject.__setattr__ as a result of a port assignment, e.g., 779 # "obj1.portA = obj2.portB", or via VectorPortRef.__setitem__, 780 # e.g., "obj1.portA[3] = obj2.portB". 781 def connect(self, other): 782 if isinstance(other, VectorPortRef): 783 # reference to plain VectorPort is implicit append 784 other = other._get_next() 785 if not (isinstance(other, PortRef) or proxy.isproxy(other)): 786 raise TypeError, \ 787 "assigning non-port reference '%s' to port '%s'" \ 788 % (other, self) 789 if self.peer and not proxy.isproxy(self.peer): 790 print "warning: overwriting port", self, \ 791 "value", self.peer, "with", other |
792 self.peer = other |
793 assert(not isinstance(self.peer, VectorPortRef)) 794 if isinstance(other, PortRef) and other.peer is not self: 795 other.connect(self) |
796 |
797 def clone(self, simobj, memo): 798 if memo.has_key(self): 799 return memo[self] |
800 newRef = copy.copy(self) |
801 memo[self] = newRef 802 newRef.simobj = simobj |
803 assert(isSimObject(newRef.simobj)) |
804 if self.peer and not proxy.isproxy(self.peer): 805 peerObj = memo[self.peer.simobj] 806 newRef.peer = self.peer.clone(peerObj, memo) 807 assert(not isinstance(newRef.peer, VectorPortRef)) |
808 return newRef 809 |
810 def unproxy(self, simobj): 811 assert(simobj is self.simobj) 812 if proxy.isproxy(self.peer): 813 try: 814 realPeer = self.peer.unproxy(self.simobj) 815 except: 816 print "Error in unproxying port '%s' of %s" % \ 817 (self.name, self.simobj.path()) 818 raise 819 self.connect(realPeer) 820 |
821 # Call C++ to create corresponding port connection between C++ objects 822 def ccConnect(self): 823 if self.ccConnected: # already done this 824 return 825 peer = self.peer 826 cc_main.connectPorts(self.simobj.getCCObject(), self.name, self.index, 827 peer.simobj.getCCObject(), peer.name, peer.index) 828 self.ccConnected = True 829 peer.ccConnected = True 830 |
831# A reference to an individual element of a VectorPort... much like a 832# PortRef, but has an index. 833class VectorPortElementRef(PortRef): 834 def __init__(self, simobj, name, index): 835 PortRef.__init__(self, simobj, name) 836 self.index = index 837 838 def __str__(self): 839 return '%s.%s[%d]' % (self.simobj, self.name, self.index) 840 841# A reference to a complete vector-valued port (not just a single element). 842# Can be indexed to retrieve individual VectorPortElementRef instances. 843class VectorPortRef(object): 844 def __init__(self, simobj, name): 845 assert(isSimObject(simobj) or isSimObjectClass(simobj)) 846 self.simobj = simobj 847 self.name = name 848 self.elements = [] 849 850 # for config.ini, print peer's name (not ours) 851 def ini_str(self): 852 return ' '.join([el.ini_str() for el in self.elements]) 853 854 def __getitem__(self, key): 855 if not isinstance(key, int): 856 raise TypeError, "VectorPort index must be integer" 857 if key >= len(self.elements): 858 # need to extend list 859 ext = [VectorPortElementRef(self.simobj, self.name, i) 860 for i in range(len(self.elements), key+1)] 861 self.elements.extend(ext) 862 return self.elements[key] 863 864 def _get_next(self): 865 return self[len(self.elements)] 866 867 def __setitem__(self, key, value): 868 if not isinstance(key, int): 869 raise TypeError, "VectorPort index must be integer" 870 self[key].connect(value) 871 872 def connect(self, other): 873 # reference to plain VectorPort is implicit append 874 self._get_next().connect(other) 875 876 def unproxy(self, simobj): 877 [el.unproxy(simobj) for el in self.elements] 878 879 def ccConnect(self): 880 [el.ccConnect() for el in self.elements] 881 |
882# Port description object. Like a ParamDesc object, this represents a 883# logical port in the SimObject class, not a particular port on a 884# SimObject instance. The latter are represented by PortRef objects. 885class Port(object): |
886 # Port("description") or Port(default, "description") 887 def __init__(self, *args): 888 if len(args) == 1: 889 self.desc = args[0] 890 elif len(args) == 2: 891 self.default = args[0] 892 self.desc = args[1] 893 else: 894 raise TypeError, 'wrong number of arguments' 895 # self.name is set by SimObject class on assignment 896 # e.g., pio_port = Port("blah") sets self.name to 'pio_port' |
897 898 # Generate a PortRef for this port on the given SimObject with the 899 # given name |
900 def makeRef(self, simobj): 901 return PortRef(simobj, self.name) |
902 903 # Connect an instance of this port (on the given SimObject with 904 # the given name) with the port described by the supplied PortRef |
905 def connect(self, simobj, ref): 906 self.makeRef(simobj).connect(ref) |
907 908# VectorPort description object. Like Port, but represents a vector 909# of connections (e.g., as on a Bus). 910class VectorPort(Port): |
911 def __init__(self, *args): 912 Port.__init__(self, *args) |
913 self.isVec = True 914 |
915 def makeRef(self, simobj): 916 return VectorPortRef(simobj, self.name) |
917 |
918 919 |
920__all__ = ['Param', 'VectorParam', 921 'Enum', 'Bool', 'String', 'Float', 922 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 923 'Int32', 'UInt32', 'Int64', 'UInt64', 924 'Counter', 'Addr', 'Tick', 'Percent', 925 'TcpPort', 'UdpPort', 'EthernetAddr', 926 'MemorySize', 'MemorySize32', 927 'Latency', 'Frequency', 'RootClock', 'Clock', 928 'NetworkBandwidth', 'MemoryBandwidth', 929 'Range', 'AddrRange', 'TickRange', 930 'MaxAddr', 'MaxTick', 'AllMemory', 931 'NextEthernetAddr', 'NULL', 932 'Port', 'VectorPort'] 933 934# see comment on imports at end of __init__.py. 935from SimObject import isSimObject, isSimObjectSequence, isSimObjectClass 936import proxy 937import objects 938import cc_main |