params.py (3103:330ec058b026) params.py (3105:993f1abefd67)
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):
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, isVec):
756 assert(isSimObject(simobj))
755 def __init__(self, simobj, name):
756 assert(isSimObject(simobj) or isSimObjectClass(simobj))
757 self.simobj = simobj
758 self.name = name
757 self.simobj = simobj
758 self.name = name
759 self.index = -1
760 self.isVec = isVec # is this a vector port?
761 self.peer = None # not associated with another port yet
762 self.ccConnected = False # C++ port connection done?
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
763
764 def __str__(self):
762
763 def __str__(self):
765 ext = ''
766 if self.isVec:
767 ext = '[%d]' % self.index
768 return '%s.%s%s' % (self.simobj.path(), self.name, ext)
764 return '%s.%s' % (self.simobj, self.name)
769
765
770 # Set peer port reference. Called via __setattr__ as a result of
771 # a port assignment, e.g., "obj1.port1 = obj2.port2".
772 def setPeer(self, other):
773 if self.isVec:
774 curMap = self.simobj._port_map.get(self.name, [])
775 self.index = len(curMap)
776 curMap.append(other)
777 else:
778 curMap = self.simobj._port_map.get(self.name)
779 if curMap and not self.isVec:
780 print "warning: overwriting port", self.simobj, self.name
781 curMap = other
782 self.simobj._port_map[self.name] = curMap
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
783 self.peer = 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)
784
796
785 def clone(self, memo):
797 def clone(self, simobj, memo):
798 if memo.has_key(self):
799 return memo[self]
786 newRef = copy.copy(self)
800 newRef = copy.copy(self)
801 memo[self] = newRef
802 newRef.simobj = simobj
787 assert(isSimObject(newRef.simobj))
803 assert(isSimObject(newRef.simobj))
788 newRef.simobj = newRef.simobj(_memo=memo)
789 # Tricky: if I'm the *second* PortRef in the pair to be
790 # cloned, then my peer is still in the middle of its clone
791 # method, and thus hasn't returned to its owner's
792 # SimObject.__init__ to get installed in _port_map. As a
793 # result I have no way of finding the *new* peer object. So I
794 # mark myself as "waiting" for my peer, and I let the *first*
795 # PortRef clone call set up both peer pointers after I return.
796 newPeer = newRef.simobj._port_map.get(self.name)
797 if newPeer:
798 if self.isVec:
799 assert(self.index != -1)
800 newPeer = newPeer[self.index]
801 # other guy is all set up except for his peer pointer
802 assert(newPeer.peer == -1) # peer must be waiting for handshake
803 newPeer.peer = newRef
804 newRef.peer = newPeer
805 else:
806 # other guy is in clone; just wait for him to do the work
807 newRef.peer = -1 # mark as waiting for handshake
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
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
810 # Call C++ to create corresponding port connection between C++ objects
811 def ccConnect(self):
812 if self.ccConnected: # already done this
813 return
814 peer = self.peer
815 cc_main.connectPorts(self.simobj.getCCObject(), self.name, self.index,
816 peer.simobj.getCCObject(), peer.name, peer.index)
817 self.ccConnected = True
818 peer.ccConnected = True
819
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
820# Port description object. Like a ParamDesc object, this represents a
821# logical port in the SimObject class, not a particular port on a
822# SimObject instance. The latter are represented by PortRef objects.
823class Port(object):
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):
824 def __init__(self, desc):
825 self.desc = desc
826 self.isVec = False
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'
827
828 # Generate a PortRef for this port on the given SimObject with the
829 # given name
897
898 # Generate a PortRef for this port on the given SimObject with the
899 # given name
830 def makeRef(self, simobj, name):
831 return PortRef(simobj, name, self.isVec)
900 def makeRef(self, simobj):
901 return PortRef(simobj, self.name)
832
833 # Connect an instance of this port (on the given SimObject with
834 # the given name) with the port described by the supplied PortRef
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
835 def connect(self, simobj, name, ref):
836 if not isinstance(ref, PortRef):
837 raise TypeError, \
838 "assigning non-port reference port '%s'" % name
839 myRef = self.makeRef(simobj, name)
840 myRef.setPeer(ref)
841 ref.setPeer(myRef)
905 def connect(self, simobj, ref):
906 self.makeRef(simobj).connect(ref)
842
843# VectorPort description object. Like Port, but represents a vector
844# of connections (e.g., as on a Bus).
845class VectorPort(Port):
907
908# VectorPort description object. Like Port, but represents a vector
909# of connections (e.g., as on a Bus).
910class VectorPort(Port):
846 def __init__(self, desc):
847 Port.__init__(self, desc)
911 def __init__(self, *args):
912 Port.__init__(self, *args)
848 self.isVec = True
849
913 self.isVec = True
914
915 def makeRef(self, simobj):
916 return VectorPortRef(simobj, self.name)
850
917
918
919
851__all__ = ['Param', 'VectorParam',
852 'Enum', 'Bool', 'String', 'Float',
853 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16',
854 'Int32', 'UInt32', 'Int64', 'UInt64',
855 'Counter', 'Addr', 'Tick', 'Percent',
856 'TcpPort', 'UdpPort', 'EthernetAddr',
857 'MemorySize', 'MemorySize32',
858 'Latency', 'Frequency', 'RootClock', 'Clock',
859 'NetworkBandwidth', 'MemoryBandwidth',
860 'Range', 'AddrRange', 'TickRange',
861 'MaxAddr', 'MaxTick', 'AllMemory',
862 'NextEthernetAddr', 'NULL',
863 'Port', 'VectorPort']
864
865# see comment on imports at end of __init__.py.
866from SimObject import isSimObject, isSimObjectSequence, isSimObjectClass
867import proxy
868import objects
869import cc_main
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