Port: Stricter port bind/unbind semantics
authorAndreas Hansson <andreas.hansson@arm.com>
Tue, 28 Aug 2012 18:30:27 +0000 (14:30 -0400)
committerAndreas Hansson <andreas.hansson@arm.com>
Tue, 28 Aug 2012 18:30:27 +0000 (14:30 -0400)
This patch tightens up the semantics around port binding and checks
that the ports that are being bound are currently not connected, and
similarly connected before unbind is called.

The patch consequently also changes the order of the unbind and bind
for the switching of CPUs to ensure that the rules are adhered
to. Previously the ports would be "over-written" without any check.

There are no changes in behaviour due to this patch, and the only
place where the unbind functionality is used is in the CPU.

src/cpu/base.cc
src/mem/port.cc
src/mem/port.hh

index c1b1e6d3642b38db75fd567ee745d69adfdd37ad..ff832f5624326b1cdcb4e21ab944954d425a142b 100644 (file)
@@ -389,17 +389,21 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
         MasterPort *new_dtb_port = newTC->getDTBPtr()->getMasterPort();
 
         // Move over any table walker ports if they exist
-        if (new_itb_port && !new_itb_port->isConnected()) {
+        if (new_itb_port) {
+            assert(!new_itb_port->isConnected());
             assert(old_itb_port);
+            assert(old_itb_port->isConnected());
             SlavePort &slavePort = old_itb_port->getSlavePort();
+            old_itb_port->unbind();
             new_itb_port->bind(slavePort);
-            old_itb_port->unBind();
         }
-        if (new_dtb_port && !new_dtb_port->isConnected()) {
+        if (new_dtb_port) {
+            assert(!new_dtb_port->isConnected());
             assert(old_dtb_port);
+            assert(old_dtb_port->isConnected());
             SlavePort &slavePort = old_dtb_port->getSlavePort();
+            old_dtb_port->unbind();
             new_dtb_port->bind(slavePort);
-            old_dtb_port->unBind();
         }
 
         // Checker whether or not we have to transfer CheckerCPU
@@ -417,17 +421,21 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
                 newChecker->getDTBPtr()->getMasterPort();
 
             // Move over any table walker ports if they exist for checker
-            if (new_checker_itb_port && !new_checker_itb_port->isConnected()) {
+            if (new_checker_itb_port) {
+                assert(!new_checker_itb_port->isConnected());
                 assert(old_checker_itb_port);
-                SlavePort &slavePort = old_checker_itb_port->getSlavePort();;
+                assert(old_checker_itb_port->isConnected());
+                SlavePort &slavePort = old_checker_itb_port->getSlavePort();
+                old_checker_itb_port->unbind();
                 new_checker_itb_port->bind(slavePort);
-                old_checker_itb_port->unBind();
             }
-            if (new_checker_dtb_port && !new_checker_dtb_port->isConnected()) {
+            if (new_checker_dtb_port) {
+                assert(!new_checker_dtb_port->isConnected());
                 assert(old_checker_dtb_port);
-                SlavePort &slavePort = old_checker_dtb_port->getSlavePort();;
+                assert(old_checker_dtb_port->isConnected());
+                SlavePort &slavePort = old_checker_dtb_port->getSlavePort();
+                old_checker_dtb_port->unbind();
                 new_checker_dtb_port->bind(slavePort);
-                old_checker_dtb_port->unBind();
             }
         }
     }
@@ -444,18 +452,21 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
             schedule(profileEvent, curTick());
     }
 
-    // Connect new CPU to old CPU's memory only if new CPU isn't
-    // connected to anything.  Also connect old CPU's memory to new
-    // CPU.
-    if (!getInstPort().isConnected()) {
-        getInstPort().bind(oldCPU->getInstPort().getSlavePort());
-        oldCPU->getInstPort().unBind();
-    }
-
-    if (!getDataPort().isConnected()) {
-        getDataPort().bind(oldCPU->getDataPort().getSlavePort());
-        oldCPU->getDataPort().unBind();
-    }
+    // All CPUs have an instruction and a data port, and the new CPU's
+    // ports are dangling while the old CPU has its ports connected
+    // already. Unbind the old CPU and then bind the ports of the one
+    // we are switching to.
+    assert(!getInstPort().isConnected());
+    assert(oldCPU->getInstPort().isConnected());
+    SlavePort &inst_peer_port = oldCPU->getInstPort().getSlavePort();
+    oldCPU->getInstPort().unbind();
+    getInstPort().bind(inst_peer_port);
+
+    assert(!getDataPort().isConnected());
+    assert(oldCPU->getDataPort().isConnected());
+    SlavePort &data_peer_port = oldCPU->getDataPort().getSlavePort();
+    oldCPU->getDataPort().unbind();
+    getDataPort().bind(data_peer_port);
 }
 
 
index 3827994fb93bba839b5d4be7145204af2ed6e9d6..9b65da756e46e8053f41e5c04d3c8e0d2e3fb0c5 100644 (file)
@@ -82,14 +82,22 @@ MasterPort::getSlavePort() const
 }
 
 void
-MasterPort::unBind()
+MasterPort::unbind()
 {
+    if (_slavePort == NULL)
+        panic("Attempting to unbind master port %s that is not connected\n",
+              name());
+    _slavePort->unbind();
     _slavePort = NULL;
 }
 
 void
 MasterPort::bind(SlavePort& slave_port)
 {
+    if (_slavePort != NULL)
+        panic("Attempting to bind master port %s that is already connected\n",
+              name());
+
     // master port keeps track of the slave port
     _slavePort = &slave_port;
 
@@ -173,7 +181,7 @@ SlavePort::~SlavePort()
 }
 
 void
-SlavePort::unBind()
+SlavePort::unbind()
 {
     _masterPort = NULL;
 }
index eac92791e92963e4e8e6fb4f31b2572f77c64674..631725ce18dbc5dcd3056cf8ed0622c2b74adce8 100644 (file)
@@ -140,8 +140,17 @@ class MasterPort : public Port
                PortID id = InvalidPortID);
     virtual ~MasterPort();
 
-    void unBind();
+    /**
+     * Bind this master port to a slave port. This also does the
+     * mirror action and binds the slave port to the master port.
+     */
     void bind(SlavePort& slave_port);
+
+    /**
+     * Unbind this master port and the associated slave port.
+     */
+    void unbind();
+
     SlavePort& getSlavePort() const;
     bool isConnected() const;
 
@@ -298,8 +307,6 @@ class SlavePort : public Port
               PortID id = InvalidPortID);
     virtual ~SlavePort();
 
-    void unBind();
-    void bind(MasterPort& master_port);
     MasterPort& getMasterPort() const;
     bool isConnected() const;
 
@@ -386,6 +393,18 @@ class SlavePort : public Port
 
   protected:
 
+    /**
+     * Called by the master port to unbind. Should never be called
+     * directly.
+     */
+    void unbind();
+
+    /**
+     * Called by the master port to bind. Should never be called
+     * directly.
+     */
+    void bind(MasterPort& master_port);
+
     /**
      * Receive an atomic request packet from the master port.
      */