Move SimObject creation and Port connection loops
authorSteve Reinhardt <stever@eecs.umich.edu>
Wed, 14 Jun 2006 03:19:28 +0000 (23:19 -0400)
committerSteve Reinhardt <stever@eecs.umich.edu>
Wed, 14 Jun 2006 03:19:28 +0000 (23:19 -0400)
into Python.
Add Port and VectorPort objects and support for
specifying port connections via assignment.
The whole C++ ConfigNode hierarchy is gone now, as are
C++ Connector objects.

configs/test/fs.py:
configs/test/test.py:
    Rewrite for new port connector syntax.
src/SConscript:
    Remove unneeded files:
    - mem/connector.*
    - sim/config*
src/dev/io_device.hh:
src/mem/bridge.cc:
src/mem/bridge.hh:
src/mem/bus.cc:
src/mem/bus.hh:
src/mem/mem_object.hh:
src/mem/physical.cc:
src/mem/physical.hh:
    Allow getPort() to take an optional index to
    support vector ports (eventually).
src/python/m5/__init__.py:
    Move SimObject construction and port connection
    operations into Python (with C++ calls).
src/python/m5/config.py:
    Move SimObject construction and port connection
    operations into Python (with C++ calls).
    Add support for declaring and connecting MemObject
    ports in Python.
src/python/m5/objects/Bus.py:
src/python/m5/objects/PhysicalMemory.py:
    Add port declaration.
src/sim/builder.cc:
src/sim/builder.hh:
src/sim/serialize.cc:
src/sim/serialize.hh:
    ConfigNodes are gone; builder just gets the
    name of a .ini file section now.
src/sim/main.cc:
    Move SimObject construction and port connection
    operations into Python (with C++ calls).
    Split remaining initialization operations into two parts,
    loadIniFile() and finalInit().
src/sim/param.cc:
src/sim/param.hh:
    SimObject resolution done globally in Python now
    (not via ConfigNode hierarchy).
src/sim/sim_object.cc:
    Remove unneeded #include.

--HG--
extra : convert_revision : 2fa4001eaaec0c9a4231ef6e854f8e156d930dfe

23 files changed:
configs/test/fs.py
configs/test/test.py
src/SConscript
src/dev/io_device.hh
src/mem/bridge.cc
src/mem/bridge.hh
src/mem/bus.cc
src/mem/bus.hh
src/mem/mem_object.hh
src/mem/physical.cc
src/mem/physical.hh
src/python/m5/__init__.py
src/python/m5/config.py
src/python/m5/objects/Bus.py
src/python/m5/objects/PhysicalMemory.py
src/sim/builder.cc
src/sim/builder.hh
src/sim/main.cc
src/sim/param.cc
src/sim/param.hh
src/sim/serialize.cc
src/sim/serialize.hh
src/sim/sim_object.cc

index 55e7003a49f4945dd378702da79238589c32ed9a..333a4dfafe50945fdc7883dfdcebdc378a0f247c 100644 (file)
@@ -154,40 +154,40 @@ class LinuxAlphaSystem(LinuxAlphaSystem):
     magicbus2 = Bus(bus_id=1)
     bridge = Bridge()
     physmem = PhysicalMemory(range = AddrRange('128MB'))
-    c0a = Connector(side_a=Parent.magicbus, side_b=Parent.bridge, side_b_name="side_a")
-    c0b = Connector(side_a=Parent.magicbus2, side_b=Parent.bridge, side_b_name="side_b")
+    bridge.side_a = magicbus
+    bridge.side_b = magicbus2
     c1 = Connector(side_a=Parent.physmem, side_b=Parent.magicbus2)
     tsunami = LinuxTsunami()
-    c2 = Connector(side_a=Parent.tsunami.cchip, side_a_name='pio', side_b=Parent.magicbus)
-    c3 = Connector(side_a=Parent.tsunami.pchip, side_a_name='pio', side_b=Parent.magicbus)
-    c4 = Connector(side_a=Parent.tsunami.pciconfig, side_a_name='pio', side_b=Parent.magicbus)
-    c5 = Connector(side_a=Parent.tsunami.fake_sm_chip, side_a_name='pio', side_b=Parent.magicbus)
-    c6 = Connector(side_a=Parent.tsunami.ethernet, side_a_name='pio', side_b=Parent.magicbus)
-    c6a = Connector(side_a=Parent.tsunami.ethernet, side_a_name='dma', side_b=Parent.magicbus)
-    c7 = Connector(side_a=Parent.tsunami.fake_uart1, side_a_name='pio', side_b=Parent.magicbus)
-    c8 = Connector(side_a=Parent.tsunami.fake_uart2, side_a_name='pio', side_b=Parent.magicbus)
-    c9 = Connector(side_a=Parent.tsunami.fake_uart3, side_a_name='pio', side_b=Parent.magicbus)
-    c10 = Connector(side_a=Parent.tsunami.fake_uart4, side_a_name='pio', side_b=Parent.magicbus)
-    c11 = Connector(side_a=Parent.tsunami.ide, side_a_name='pio', side_b=Parent.magicbus)
-    c13 = Connector(side_a=Parent.tsunami.ide, side_a_name='dma', side_b=Parent.magicbus)
-    c12 = Connector(side_a=Parent.tsunami.fake_ppc, side_a_name='pio', side_b=Parent.magicbus)
-    c14 = Connector(side_a=Parent.tsunami.fake_OROM, side_a_name='pio', side_b=Parent.magicbus)
-    c16 = Connector(side_a=Parent.tsunami.fake_pnp_addr, side_a_name='pio', side_b=Parent.magicbus)
-    c17 = Connector(side_a=Parent.tsunami.fake_pnp_write, side_a_name='pio', side_b=Parent.magicbus)
-    c18 = Connector(side_a=Parent.tsunami.fake_pnp_read0, side_a_name='pio', side_b=Parent.magicbus)
-    c19 = Connector(side_a=Parent.tsunami.fake_pnp_read1, side_a_name='pio', side_b=Parent.magicbus)
-    c20 = Connector(side_a=Parent.tsunami.fake_pnp_read2, side_a_name='pio', side_b=Parent.magicbus)
-    c21 = Connector(side_a=Parent.tsunami.fake_pnp_read3, side_a_name='pio', side_b=Parent.magicbus)
-    c22 = Connector(side_a=Parent.tsunami.fake_pnp_read4, side_a_name='pio', side_b=Parent.magicbus)
-    c23 = Connector(side_a=Parent.tsunami.fake_pnp_read5, side_a_name='pio', side_b=Parent.magicbus)
-    c24 = Connector(side_a=Parent.tsunami.fake_pnp_read6, side_a_name='pio', side_b=Parent.magicbus)
-    c25 = Connector(side_a=Parent.tsunami.fake_pnp_read7, side_a_name='pio', side_b=Parent.magicbus)
-    c27 = Connector(side_a=Parent.tsunami.fake_ata0, side_a_name='pio', side_b=Parent.magicbus)
-    c28 = Connector(side_a=Parent.tsunami.fake_ata1, side_a_name='pio', side_b=Parent.magicbus)
-    c30 = Connector(side_a=Parent.tsunami.fb, side_a_name='pio', side_b=Parent.magicbus)
-    c31 = Connector(side_a=Parent.tsunami.io, side_a_name='pio', side_b=Parent.magicbus)
-    c32 = Connector(side_a=Parent.tsunami.uart, side_a_name='pio', side_b=Parent.magicbus)
-    c33 = Connector(side_a=Parent.tsunami.console, side_a_name='pio', side_b=Parent.magicbus)
+    tsunami.cchip.pio = magicbus
+    tsunami.pchip.pio = magicbus
+    tsunami.pciconfig.pio = magicbus
+    tsunami.fake_sm_chip.pio = magicbus
+    tsunami.ethernet.pio = magicbus
+    tsunami.ethernet.dma = magicbus
+    tsunami.fake_uart1.pio = magicbus
+    tsunami.fake_uart2.pio = magicbus
+    tsunami.fake_uart3.pio = magicbus
+    tsunami.fake_uart4.pio = magicbus
+    tsunami.ide.pio = magicbus
+    tsunami.ide.dma = magicbus
+    tsunami.fake_ppc.pio = magicbus
+    tsunami.fake_OROM.pio = magicbus
+    tsunami.fake_pnp_addr.pio = magicbus
+    tsunami.fake_pnp_write.pio = magicbus
+    tsunami.fake_pnp_read0.pio = magicbus
+    tsunami.fake_pnp_read1.pio = magicbus
+    tsunami.fake_pnp_read2.pio = magicbus
+    tsunami.fake_pnp_read3.pio = magicbus
+    tsunami.fake_pnp_read4.pio = magicbus
+    tsunami.fake_pnp_read5.pio = magicbus
+    tsunami.fake_pnp_read6.pio = magicbus
+    tsunami.fake_pnp_read7.pio = magicbus
+    tsunami.fake_ata0.pio = magicbus
+    tsunami.fake_ata1.pio = magicbus
+    tsunami.fb.pio = magicbus
+    tsunami.io.pio = magicbus
+    tsunami.uart.pio = magicbus
+    tsunami.console.pio = magicbus
     raw_image = RawDiskImage(image_file=disk('linux-latest.img'),
                              read_only=True)
     simple_disk = SimpleDisk(disk=Parent.raw_image)
index 2ece9e67528cdc22685e5716ef9706947be04fad..ae85af1128db6bb1e633d06134964edcd17046ec 100644 (file)
@@ -41,7 +41,7 @@ cpu.workload = process
 cpu.mem = magicbus
 
 system = System(physmem = mem, cpu = cpu)
-system.c1 =  Connector(side_a = mem, side_b = magicbus)
+mem.port = magicbus.port
 root = Root(system = system)
 
 # instantiate configuration
index a1c18711c7d0ecee217619a6ff259efa9aa50ff6..e6ed43804c9858242eb8505c46fb23a509f8d8f0 100644 (file)
@@ -97,14 +97,12 @@ base_sources = Split('''
         
         mem/bridge.cc
         mem/bus.cc
-        mem/connector.cc
         mem/mem_object.cc
         mem/packet.cc
         mem/physical.cc
         mem/port.cc
 
        sim/builder.cc
-       sim/configfile.cc
        sim/debug.cc
        sim/eventq.cc
        sim/faults.cc
index 195ca0fb76af25fc502ec765bdff1f1ec80910a9..cd2c25eeb7e95ae75ac02e6bde9f8da98f6315b4 100644 (file)
@@ -247,7 +247,7 @@ class PioDevice : public MemObject
 
     virtual void init();
 
-    virtual Port *getPort(const std::string &if_name)
+    virtual Port *getPort(const std::string &if_name, int idx = -1)
     {
         if (if_name == "pio") {
             if (pioPort != NULL)
@@ -309,7 +309,7 @@ class DmaDevice : public PioDevice
 
     bool dmaPending() { return dmaPort->dmaPending(); }
 
-    virtual Port *getPort(const std::string &if_name)
+    virtual Port *getPort(const std::string &if_name, int idx = -1)
     {
         if (if_name == "pio") {
             if (pioPort != NULL)
index 3718cbaaf30ed4cfb328fe522b21e920af43e850..29ea2e12f4181dea33cd8c9427835369b5d65de2 100644 (file)
@@ -59,7 +59,7 @@ Bridge::Bridge(const std::string &n, int qsa, int qsb,
 }
 
 Port *
-Bridge::getPort(const std::string &if_name)
+Bridge::getPort(const std::string &if_name, int idx)
 {
     BridgePort *port;
 
index 37fb92662e1781d9f5cf1be9ece4987ad74bbfbd..b3525d3e0ffbcf1031ec675e50fcecabe4990595 100644 (file)
@@ -177,7 +177,7 @@ class Bridge : public MemObject
   public:
 
     /** A function used to return the port associated with this bus object. */
-    virtual Port *getPort(const std::string &if_name);
+    virtual Port *getPort(const std::string &if_name, int idx = -1);
 
     virtual void init();
 
index 919acd23c7cc0390b87d5223920130884f2352cf..19a3dc9e407db6b89459b8a49ce0002bb53c9da6 100644 (file)
@@ -38,7 +38,7 @@
 #include "sim/builder.hh"
 
 Port *
-Bus::getPort(const std::string &if_name)
+Bus::getPort(const std::string &if_name, int idx)
 {
     // if_name ignored?  forced to be empty?
     int id = interfaces.size();
index 50bfba6e4a27b02f91c663b30ce8dbd8179ea4bc..c2b78c31fd2f80ecade5c188fe9009a817ce1256 100644 (file)
@@ -161,7 +161,7 @@ class Bus : public MemObject
   public:
 
     /** A function used to return the port associated with this bus object. */
-    virtual Port *getPort(const std::string &if_name);
+    virtual Port *getPort(const std::string &if_name, int idx = -1);
 
     virtual void init();
 
index ac547619d27897f3e3e717d4d73117a40c4e685c..c81ea03d832fee79ca2180fa164c2a844cb1cc1e 100644 (file)
@@ -50,7 +50,7 @@ class MemObject : public SimObject
 
   public:
     /** Additional function to return the Port of a memory object. */
-    virtual Port *getPort(const std::string &if_name) = 0;
+    virtual Port *getPort(const std::string &if_name, int idx = -1) = 0;
 };
 
 #endif //__MEM_MEM_OBJECT_HH__
index fb31fb4a3632bdc99fd948643ad1fa3607fd99fe..2d66602ab480fcded1a3756940799ee9458a0808 100644 (file)
@@ -173,9 +173,9 @@ PhysicalMemory::doFunctionalAccess(Packet *pkt)
 }
 
 Port *
-PhysicalMemory::getPort(const std::string &if_name)
+PhysicalMemory::getPort(const std::string &if_name, int idx)
 {
-    if (if_name == "") {
+    if (if_name == "port" && idx == -1) {
         if (port != NULL)
            panic("PhysicalMemory::getPort: additional port requested to memory!");
         port = new MemoryPort(name() + "-port", this);
index 88ea543da5887722967454ab26965f5c4fe7e399..50fa75ed3e865ec9803faab421419ab6fc3ae21b 100644 (file)
@@ -108,7 +108,7 @@ class PhysicalMemory : public MemObject
   public:
     int deviceBlockSize();
     void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
-    virtual Port *getPort(const std::string &if_name);
+    virtual Port *getPort(const std::string &if_name, int idx = -1);
     void virtual init();
 
     // fast back-door memory access for vtophys(), remote gdb, etc.
index 60a61d66eb553e96efe8c32eb57b4c721afcf52c..208d11b694efd85f18926b92aed6fdd07484f74d 100644 (file)
@@ -80,6 +80,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):
@@ -89,7 +99,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()
index 97e13c900c80189e26aeb49231a0ed4addae5212..f23fd2c6fa37d834d32332cbf350243a5f952911 100644 (file)
@@ -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']
 
index c37dab438ab8232370dd28e5551dc2dfd3643f79..019e15034627e5145370d32d4bf01e2e84648ffe 100644 (file)
@@ -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")
index bed90d555918fe142005b1a3891d8e57ac2ae400..9cc7510a285fd05b14b1ca50e970fbf7554960d5 100644 (file)
@@ -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")
index 121275c833f340130beb73b077b68837dcdf0098..9074cc8995afe79f3da9c002ed91ae89d00aab80 100644 (file)
 #include "base/inifile.hh"
 #include "base/misc.hh"
 #include "sim/builder.hh"
-#include "sim/configfile.hh"
-#include "sim/config_node.hh"
 #include "sim/host.hh"
 #include "sim/sim_object.hh"
 #include "sim/root.hh"
 
 using namespace std;
 
-SimObjectBuilder::SimObjectBuilder(ConfigNode *_configNode)
-    : ParamContext(_configNode->getPath(), NoAutoInit),
-      configNode(_configNode)
+SimObjectBuilder::SimObjectBuilder(const std::string &_iniSection)
+    : ParamContext(_iniSection, NoAutoInit)
 {
 }
 
@@ -78,8 +75,7 @@ SimObjectBuilder::parseParams(IniFile &iniFile)
 void
 SimObjectBuilder::printErrorProlog(ostream &os)
 {
-    ccprintf(os, "Error creating object '%s' of type '%s':\n",
-             iniSection, configNode->getType());
+    ccprintf(os, "Error creating object '%s':\n", iniSection);
 }
 
 
@@ -112,9 +108,13 @@ SimObjectClass::SimObjectClass(const string &className, CreateFunc createFunc)
 //
 //
 SimObject *
-SimObjectClass::createObject(IniFile &configDB, ConfigNode *configNode)
+SimObjectClass::createObject(IniFile &configDB, const std::string &iniSection)
 {
-    const string &type = configNode->getType();
+    string type;
+    if (!configDB.find(iniSection, "type", type)) {
+        // no C++ type associated with this object
+        return NULL;
+    }
 
     // look up className to get appropriate createFunc
     if (classMap->find(type) == classMap->end())
@@ -125,7 +125,7 @@ SimObjectClass::createObject(IniFile &configDB, ConfigNode *configNode)
 
     // call createFunc with config hierarchy node to get object
     // builder instance (context with parameters for object creation)
-    SimObjectBuilder *objectBuilder = (*createFunc)(configNode);
+    SimObjectBuilder *objectBuilder = (*createFunc)(iniSection);
 
     assert(objectBuilder != NULL);
 
@@ -166,7 +166,7 @@ SimObjectClass::describeAllClasses(ostream &os)
         os << "[" << className << "]\n";
 
         // create dummy object builder just to instantiate parameters
-        SimObjectBuilder *objectBuilder = (*createFunc)(NULL);
+        SimObjectBuilder *objectBuilder = (*createFunc)("");
 
         // now get the object builder to describe ite params
         objectBuilder->describeParams(os);
index 8d08461557624ca4803b0717ffa0e8afb2232c30..2997fe5c339d9e6bdd7a64968dee2766be66aa46 100644 (file)
@@ -55,14 +55,8 @@ class SimObject;
 //
 class SimObjectBuilder : public ParamContext
 {
-  private:
-    // The corresponding node in the configuration hierarchy.
-    // (optional: may be null if the created object is not in the
-    // hierarchy)
-    ConfigNode *configNode;
-
   public:
-    SimObjectBuilder(ConfigNode *_configNode);
+    SimObjectBuilder(const std::string &_iniSection);
 
     virtual ~SimObjectBuilder();
 
@@ -77,9 +71,6 @@ class SimObjectBuilder : public ParamContext
     // configuration hierarchy node label and position)
     virtual const std::string &getInstanceName() { return iniSection; }
 
-    // return the configuration hierarchy node for this context.
-    virtual ConfigNode *getConfigNode() { return configNode; }
-
     // Create the actual SimObject corresponding to the parameter
     // values in this context.  This function is overridden in derived
     // classes to call a specific constructor for a particular
@@ -125,7 +116,7 @@ class SimObjectClass
     // for the object (specified by the second string argument), and
     // an optional config hierarchy node (specified by the third
     // argument).  A pointer to the new SimObjectBuilder is returned.
-    typedef SimObjectBuilder *(*CreateFunc)(ConfigNode *configNode);
+    typedef SimObjectBuilder *(*CreateFunc)(const std::string &iniSection);
 
     static std::map<std::string,CreateFunc> *classMap;
 
@@ -137,7 +128,8 @@ class SimObjectClass
 
     // create SimObject given name of class and pointer to
     // configuration hierarchy node
-    static SimObject *createObject(IniFile &configDB, ConfigNode *configNode);
+    static SimObject *createObject(IniFile &configDB,
+                                   const std::string &iniSection);
 
     // print descriptions of all parameters registered with all
     // SimObject classes
@@ -156,15 +148,15 @@ class OBJ_CLASS##Builder : public SimObjectBuilder                \
 
 #define END_DECLARE_SIM_OBJECT_PARAMS(OBJ_CLASS)               \
                                                                 \
-    OBJ_CLASS##Builder(ConfigNode *configNode);                        \
+    OBJ_CLASS##Builder(const std::string &iniSection);          \
     virtual ~OBJ_CLASS##Builder() {}                           \
                                                                 \
     OBJ_CLASS *create();                                       \
 };
 
 #define BEGIN_INIT_SIM_OBJECT_PARAMS(OBJ_CLASS)                        \
-OBJ_CLASS##Builder::OBJ_CLASS##Builder(ConfigNode *configNode) \
-    : SimObjectBuilder(configNode),
+    OBJ_CLASS##Builder::OBJ_CLASS##Builder(const std::string &iSec) \
+    : SimObjectBuilder(iSec),
 
 
 #define END_INIT_SIM_OBJECT_PARAMS(OBJ_CLASS)                  \
@@ -176,9 +168,9 @@ OBJ_CLASS *OBJ_CLASS##Builder::create()
 
 #define REGISTER_SIM_OBJECT(CLASS_NAME, OBJ_CLASS)             \
 SimObjectBuilder *                                             \
-new##OBJ_CLASS##Builder(ConfigNode *configNode)                        \
+new##OBJ_CLASS##Builder(const std::string &iniSection)          \
 {                                                              \
-    return new OBJ_CLASS##Builder(configNode);                 \
+    return new OBJ_CLASS##Builder(iniSection);                 \
 }                                                              \
                                                                 \
 SimObjectClass the##OBJ_CLASS##Class(CLASS_NAME,               \
index f3b74489d57e9f8ff0e18cd6947a1d6bdfcfa9d9..f63aec9cc4dab348d8652f6aa1bc0fb9293a0712 100644 (file)
 #include "base/time.hh"
 #include "cpu/base.hh"
 #include "cpu/smt.hh"
+#include "mem/mem_object.hh"
+#include "mem/port.hh"
 #include "sim/async.hh"
 #include "sim/builder.hh"
-#include "sim/configfile.hh"
 #include "sim/host.hh"
 #include "sim/sim_events.hh"
 #include "sim/sim_exit.hh"
@@ -296,26 +297,109 @@ main(int argc, char **argv)
     Py_Finalize();
 }
 
+IniFile inifile;
 
-/// Initialize C++ configuration.  Exported to Python via SWIG; invoked
-/// from m5.instantiate().
+SimObject *
+createSimObject(const string &name)
+{
+    return SimObjectClass::createObject(inifile, name);
+}
+
+
+/**
+ * Pointer to the Python function that maps names to SimObjects.
+ */
+PyObject *resolveFunc = NULL;
+
+/**
+ * Convert a pointer to the Python object that SWIG wraps around a C++
+ * SimObject pointer back to the actual C++ pointer.  See main.i.
+ */
+extern "C" SimObject *convertSwigSimObjectPtr(PyObject *);
+
+
+SimObject *
+resolveSimObject(const string &name)
+{
+    PyObject *pyPtr = PyEval_CallFunction(resolveFunc, "(s)", name.c_str());
+    if (pyPtr == NULL) {
+        PyErr_Print();
+        panic("resolveSimObject: failure on call to Python for %s", name);
+    }
+
+    SimObject *simObj = convertSwigSimObjectPtr(pyPtr);
+    if (simObj == NULL)
+        panic("resolveSimObject: failure on pointer conversion for %s", name);
+
+    return simObj;
+}
+
+
+/**
+ * Load config.ini into C++ database.  Exported to Python via SWIG;
+ * invoked from m5.instantiate().
+ */
 void
-initialize()
+loadIniFile(PyObject *_resolveFunc)
 {
+    resolveFunc = _resolveFunc;
     configStream = simout.find("config.out");
 
     // The configuration database is now complete; start processing it.
-    IniFile inifile;
     inifile.load("config.ini");
 
     // Initialize statistics database
     Stats::InitSimStats();
+}
+
+
+/**
+ * Look up a MemObject port.  Helper function for connectPorts().
+ */
+Port *
+lookupPort(SimObject *so, const std::string &name, int i)
+{
+    MemObject *mo = dynamic_cast<MemObject *>(so);
+    if (mo == NULL) {
+        warn("error casting SimObject %s to MemObject", so->name());
+        return NULL;
+    }
+
+    Port *p = mo->getPort(name, i);
+    if (p == NULL)
+        warn("error looking up port %s on object %s", name, so->name());
+    return p;
+}
 
-    // Now process the configuration hierarchy and create the SimObjects.
-    ConfigHierarchy configHierarchy(inifile);
-    configHierarchy.build();
-    configHierarchy.createSimObjects();
 
+/**
+ * Connect the described MemObject ports.  Called from Python via SWIG.
+ */
+int
+connectPorts(SimObject *o1, const std::string &name1, int i1,
+             SimObject *o2, const std::string &name2, int i2)
+{
+    Port *p1 = lookupPort(o1, name1, i1);
+    Port *p2 = lookupPort(o2, name2, i2);
+
+    if (p1 == NULL || p2 == NULL) {
+        warn("connectPorts: port lookup error");
+        return 0;
+    }
+
+    p1->setPeer(p2);
+    p2->setPeer(p1);
+
+    return 1;
+}
+
+/**
+ * Do final initialization steps after object construction but before
+ * start of simulation.
+ */
+void
+finalInit()
+{
     // Parse and check all non-config-hierarchy parameters.
     ParamContext::parseAllContexts(inifile);
     ParamContext::checkAllContexts();
@@ -323,20 +407,13 @@ initialize()
     // Echo all parameter settings to stats file as well.
     ParamContext::showAllContexts(*configStream);
 
-    // Any objects that can't connect themselves until after construction should
-    // do so now
-    SimObject::connectAll();
-
     // Do a second pass to finish initializing the sim objects
     SimObject::initAll();
 
     // Restore checkpointed state, if any.
+#if 0
     configHierarchy.unserializeSimObjects();
-
-    // Done processing the configuration database.
-    // Check for unreferenced entries.
-    if (inifile.printUnreferenced())
-        panic("unreferenced sections/entries in the intermediate ini file");
+#endif
 
     SimObject::regAllStats();
 
index 7f648b8e117739f2bbc2074b47197abdddfb1dee..b1c50946be166bdc18582cd3b289b11f3ea3c566 100644 (file)
@@ -39,8 +39,6 @@
 #include "base/range.hh"
 #include "base/str.hh"
 #include "base/trace.hh"
-#include "sim/config_node.hh"
-#include "sim/configfile.hh"
 #include "sim/param.hh"
 #include "sim/sim_object.hh"
 
@@ -521,7 +519,9 @@ parseSimObjectParam(ParamContext *context, const string &s, SimObject *&value)
         obj = NULL;
     }
     else {
-        obj = context->resolveSimObject(s);
+        // defined in main.cc
+        extern SimObject *resolveSimObject(const string &);
+        obj = resolveSimObject(s);
 
         if (obj == NULL)
             return false;
@@ -695,22 +695,6 @@ ParamContext::printErrorProlog(ostream &os)
     os << "Parameter error in section [" << iniSection << "]: " << endl;
 }
 
-//
-// Resolve an object name to a SimObject pointer.  The object will be
-// created as a side-effect if necessary.  If the name contains a
-// colon (e.g., "iq:IQ"), then the object is local (invisible to
-// outside this context).  If there is no colon, the name needs to be
-// resolved through the configuration hierarchy (only possible for
-// SimObjectBuilder objects, which return non-NULL for configNode()).
-//
-SimObject *
-ParamContext::resolveSimObject(const string &name)
-{
-    ConfigNode *n = getConfigNode();
-    return n ? n->resolveSimObject(name) : NULL;
-}
-
-
 //
 // static method: call parseParams() on all registered contexts
 //
index 49db17df9d317812f1e441a945410194fd497265..1bc55c1253e7ae48d6461c03d51c7f6401729b70 100644 (file)
 #include <string>
 #include <vector>
 
-#include "sim/configfile.hh"
 #include "sim/startup.hh"
 
 // forward decls
+class IniFile;
 class BaseParam;
 class SimObject;
 
@@ -132,18 +132,10 @@ class ParamContext : protected StartupCallback
     // print context information for parameter error
     virtual void printErrorProlog(std::ostream &);
 
-    // resolve a SimObject name in this context to an object pointer.
-    virtual SimObject *resolveSimObject(const std::string &name);
-
     // generate the name for this instance of this context (used as a
     // prefix to create unique names in resolveSimObject()
     virtual const std::string &getInstanceName() { return iniSection; }
 
-    // return the configuration hierarchy node for this context.  Bare
-    // ParamContext objects have no corresponding node, so the default
-    // implementation returns NULL.
-    virtual ConfigNode *getConfigNode() { return NULL; }
-
     // Parse all parameters registered with all ParamContext objects.
     static void parseAllContexts(IniFile &iniFile);
 
index 5270802d1ee46fddba24be84e033af493bca621b..07e3b8a56bac2b0a592a93216b977cf0e8fbce75 100644 (file)
@@ -44,7 +44,6 @@
 #include "base/output.hh"
 #include "base/str.hh"
 #include "base/trace.hh"
-#include "sim/config_node.hh"
 #include "sim/eventq.hh"
 #include "sim/param.hh"
 #include "sim/serialize.hh"
@@ -442,9 +441,8 @@ Serializable::create(Checkpoint *cp, const std::string &section)
 }
 
 
-Checkpoint::Checkpoint(const std::string &cpt_dir, const std::string &path,
-                       const ConfigNode *_configNode)
-    : db(new IniFile), basePath(path), configNode(_configNode), cptDir(cpt_dir)
+Checkpoint::Checkpoint(const std::string &cpt_dir, const std::string &path)
+    : db(new IniFile), basePath(path), cptDir(cpt_dir)
 {
     string filename = cpt_dir + "/" + Checkpoint::baseFilename;
     if (!db->load(filename)) {
@@ -470,9 +468,6 @@ Checkpoint::findObj(const std::string &section, const std::string &entry,
     if (!db->find(section, entry, path))
         return false;
 
-    if ((value = configNode->resolveSimObject(path)) != NULL)
-        return true;
-
     if ((value = objMap[path]) != NULL)
         return true;
 
index 1eb721cf4f1798674a31587d38bf7bf275a7a3da..1bcb235e6dc399526c8bb17c767eaccd71a8db80 100644 (file)
@@ -42,8 +42,8 @@
 #include <map>
 
 #include "sim/host.hh"
-#include "sim/configfile.hh"
 
+class IniFile;
 class Serializable;
 class Checkpoint;
 
@@ -177,7 +177,7 @@ class SerializableClass
     // an optional config hierarchy node (specified by the third
     // argument).  A pointer to the new SerializableBuilder is returned.
     typedef Serializable *(*CreateFunc)(Checkpoint *cp,
-                                         const std::string &section);
+                                        const std::string &section);
 
     static std::map<std::string,CreateFunc> *classMap;
 
@@ -191,7 +191,7 @@ class SerializableClass
     // create Serializable given name of class and pointer to
     // configuration hierarchy node
     static Serializable *createObject(Checkpoint *cp,
-                                       const std::string &section);
+                                      const std::string &section);
 };
 
 //
@@ -209,12 +209,10 @@ class Checkpoint
 
     IniFile *db;
     const std::string basePath;
-    const ConfigNode *configNode;
     std::map<std::string, Serializable*> objMap;
 
   public:
-    Checkpoint(const std::string &cpt_dir, const std::string &path,
-               const ConfigNode *_configNode);
+    Checkpoint(const std::string &cpt_dir, const std::string &path);
 
     const std::string cptDir;
 
index 117ca93250fc4795c959ee0ce2baba5bf00867f4..97e6de439a151696edada0a3d94a5bb10d159e36 100644 (file)
@@ -38,7 +38,6 @@
 #include "base/trace.hh"
 #include "base/stats/events.hh"
 #include "base/serializer.hh"
-#include "sim/configfile.hh"
 #include "sim/host.hh"
 #include "sim/sim_object.hh"
 #include "sim/stats.hh"