diff options
Diffstat (limited to 'src/python/m5')
-rw-r--r-- | src/python/m5/__init__.py | 15 | ||||
-rw-r--r-- | src/python/m5/config.py | 125 | ||||
-rw-r--r-- | src/python/m5/objects/Bus.py | 1 | ||||
-rw-r--r-- | src/python/m5/objects/PhysicalMemory.py | 1 |
4 files changed, 139 insertions, 3 deletions
diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py index 2d4825b0e..a4fc9a5e3 100644 --- a/src/python/m5/__init__.py +++ b/src/python/m5/__init__.py @@ -103,6 +103,16 @@ build_env.update(defines.m5_build_env) env = smartdict.SmartDict() env.update(os.environ) + +# Function to provide to C++ so it can look up instances based on paths +def resolveSimObject(name): + obj = config.instanceDict[name] + if not obj._ccObject: + obj.createCCObject() + if obj._ccObject == -1: + panic("resolveSimObject: recursive lookup error on %s" % name) + return obj._ccObject + # The final hook to generate .ini files. Called from the user script # once the config is built. def instantiate(root): @@ -112,7 +122,10 @@ def instantiate(root): root.print_ini() sys.stdout.close() # close config.ini sys.stdout = sys.__stdout__ # restore to original - main.initialize() # load config.ini into C++ and process it + main.loadIniFile(resolveSimObject) # load config.ini into C++ + root.createCCObject() + root.connectPorts() + main.finalInit() noDot = True # temporary until we fix dot if not noDot: dot = pydot.Dot() diff --git a/src/python/m5/config.py b/src/python/m5/config.py index 97e13c900..f23fd2c6f 100644 --- a/src/python/m5/config.py +++ b/src/python/m5/config.py @@ -133,6 +133,10 @@ class Singleton(type): # ##################################################################### + +# dict to look up SimObjects based on path +instanceDict = {} + def isSimObject(value): return isinstance(value, SimObject) @@ -200,7 +204,8 @@ class MetaSimObject(type): 'type' : types.StringType } # Attributes that can be set any time keywords = { 'check' : types.FunctionType, - 'children' : types.ListType } + 'children' : types.ListType, + 'ccObject' : types.ObjectType } # __new__ is called before __init__, and is where the statements # in the body of the class definition get loaded into the class's @@ -233,6 +238,7 @@ class MetaSimObject(type): # initialize required attributes cls._params = multidict() cls._values = multidict() + cls._ports = multidict() cls._instantiated = False # really instantiated or subclassed cls._anon_subclass_counter = 0 @@ -248,6 +254,7 @@ class MetaSimObject(type): if isinstance(base, MetaSimObject): cls._params.parent = base._params cls._values.parent = base._values + cls._ports.parent = base._ports base._instantiated = True # now process the _init_dict items @@ -259,6 +266,10 @@ class MetaSimObject(type): elif isinstance(val, ParamDesc): cls._new_param(key, val) + # port objects + elif isinstance(val, Port): + cls._ports[key] = val + # init-time-only keywords elif cls.init_keywords.has_key(key): cls._set_keyword(key, val, cls.init_keywords[key]) @@ -313,6 +324,10 @@ class MetaSimObject(type): cls._set_keyword(attr, value, cls.keywords[attr]) return + if cls._ports.has_key(attr): + self._ports[attr].connect(self, attr, value) + return + # must be SimObject param param = cls._params.get(attr, None) if param: @@ -428,6 +443,9 @@ class SimObject(object): for key,val in kwargs.iteritems(): setattr(self, key, val) + self._ccObject = None # pointer to C++ object + self._port_map = {} # map of port connections + # Use this instance as a template to create a new class. def makeClass(self, memo = {}): cls = memo.get(self) @@ -443,6 +461,11 @@ class SimObject(object): "use makeClass() to make class first" def __getattr__(self, attr): + if self._ports.has_key(attr): + # return reference that can be assigned to another port + # via __setattr__ + return self._ports[attr].makeRef(self, attr) + if self._values.has_key(attr): return self._values[attr] @@ -457,6 +480,11 @@ class SimObject(object): object.__setattr__(self, attr, value) return + if self._ports.has_key(attr): + # set up port connection + self._ports[attr].connect(self, attr, value) + return + # must be SimObject param param = self._params.get(attr, None) if param: @@ -554,6 +582,8 @@ class SimObject(object): def print_ini(self): print '[' + self.path() + ']' # .ini section header + instanceDict[self.path()] = self + if hasattr(self, 'type') and not isinstance(self, ParamContext): print 'type=%s' % self.type @@ -585,6 +615,24 @@ class SimObject(object): for child in child_names: self._children[child].print_ini() + # Call C++ to create C++ object corresponding to this object and + # (recursively) all its children + def createCCObject(self): + if self._ccObject: + return + self._ccObject = -1 + self._ccObject = m5.main.createSimObject(self.path()) + for child in self._children.itervalues(): + child.createCCObject() + + # Create C++ port connections corresponding to the connections in + # _port_map (& recursively for all children) + def connectPorts(self): + for portRef in self._port_map.itervalues(): + applyOrMap(portRef, 'ccConnect') + for child in self._children.itervalues(): + child.connectPorts() + # generate output file for 'dot' to display as a pretty graph. # this code is currently broken. def outputDot(self, dot): @@ -1419,6 +1467,78 @@ MaxAddr = Addr.max MaxTick = Tick.max AllMemory = AddrRange(0, MaxAddr) + +##################################################################### +# +# Port objects +# +# Ports are used to interconnect objects in the memory system. +# +##################################################################### + +# Port reference: encapsulates a reference to a particular port on a +# particular SimObject. +class PortRef(object): + def __init__(self, simobj, name, isVec): + self.simobj = simobj + self.name = name + self.index = -1 + self.isVec = isVec # is this a vector port? + self.peer = None # not associated with another port yet + self.ccConnected = False # C++ port connection done? + + # Set peer port reference. Called via __setattr__ as a result of + # a port assignment, e.g., "obj1.port1 = obj2.port2". + def setPeer(self, other): + if self.isVec: + curMap = self.simobj._port_map.get(self.name, []) + self.index = len(curMap) + curMap.append(other) + else: + curMap = self.simobj._port_map.get(self.name) + if curMap and not self.isVec: + print "warning: overwriting port", self.simobj, self.name + curMap = other + self.simobj._port_map[self.name] = curMap + self.peer = other + + # Call C++ to create corresponding port connection between C++ objects + def ccConnect(self): + if self.ccConnected: # already done this + return + peer = self.peer + m5.main.connectPorts(self.simobj._ccObject, self.name, self.index, + peer.simobj._ccObject, peer.name, peer.index) + self.ccConnected = True + peer.ccConnected = True + +# Port description object. Like a ParamDesc object, this represents a +# logical port in the SimObject class, not a particular port on a +# SimObject instance. The latter are represented by PortRef objects. +class Port(object): + def __init__(self, desc): + self.desc = desc + self.isVec = False + + # Generate a PortRef for this port on the given SimObject with the + # given name + def makeRef(self, simobj, name): + return PortRef(simobj, name, self.isVec) + + # Connect an instance of this port (on the given SimObject with + # the given name) with the port described by the supplied PortRef + def connect(self, simobj, name, ref): + myRef = self.makeRef(simobj, name) + myRef.setPeer(ref) + ref.setPeer(myRef) + +# VectorPort description object. Like Port, but represents a vector +# of connections (e.g., as on a Bus). +class VectorPort(Port): + def __init__(self, desc): + Port.__init__(self, desc) + self.isVec = True + ##################################################################### # __all__ defines the list of symbols that get exported when @@ -1436,5 +1556,6 @@ __all__ = ['SimObject', 'ParamContext', 'Param', 'VectorParam', 'NetworkBandwidth', 'MemoryBandwidth', 'Range', 'AddrRange', 'MaxAddr', 'MaxTick', 'AllMemory', 'Null', 'NULL', - 'NextEthernetAddr'] + 'NextEthernetAddr', + 'Port', 'VectorPort'] diff --git a/src/python/m5/objects/Bus.py b/src/python/m5/objects/Bus.py index c37dab438..019e15034 100644 --- a/src/python/m5/objects/Bus.py +++ b/src/python/m5/objects/Bus.py @@ -3,4 +3,5 @@ from MemObject import MemObject class Bus(MemObject): type = 'Bus' + port = VectorPort("vector port for connecting devices") bus_id = Param.Int(0, "blah") diff --git a/src/python/m5/objects/PhysicalMemory.py b/src/python/m5/objects/PhysicalMemory.py index bed90d555..9cc7510a2 100644 --- a/src/python/m5/objects/PhysicalMemory.py +++ b/src/python/m5/objects/PhysicalMemory.py @@ -3,6 +3,7 @@ from MemObject import * class PhysicalMemory(MemObject): type = 'PhysicalMemory' + port = Port("the access port") range = Param.AddrRange("Device Address") file = Param.String('', "memory mapped file") latency = Param.Latency(Parent.clock, "latency of an access") |