Generate more useful error messages for unconnected ports.
authorSteve Reinhardt <stever@gmail.com>
Sat, 21 Jun 2008 05:04:43 +0000 (01:04 -0400)
committerSteve Reinhardt <stever@gmail.com>
Sat, 21 Jun 2008 05:04:43 +0000 (01:04 -0400)
Force all non-default ports to provide a name and an
owner in the constructor.

17 files changed:
src/cpu/o3/fetch.hh
src/cpu/o3/fetch_impl.hh
src/cpu/o3/lsq.hh
src/cpu/o3/lsq_impl.hh
src/cpu/o3/thread_context_impl.hh
src/cpu/ozone/cpu_impl.hh
src/cpu/simple_thread.cc
src/cpu/thread_state.cc
src/mem/bridge.cc
src/mem/bus.cc
src/mem/bus.hh
src/mem/cache/cache.hh
src/mem/cache/cache_impl.hh
src/mem/mem_object.cc
src/mem/mem_object.hh
src/mem/port.cc
src/mem/port.hh

index d954bd1e7ac133607d4f250f88ddb13d10722e3e..3ada0328f6a973eecedb4f27d46bd528e558bf7f 100644 (file)
@@ -80,8 +80,8 @@ class DefaultFetch
 
       public:
         /** Default constructor. */
-        IcachePort(DefaultFetch<Impl> *_fetch)
-            : Port(_fetch->name() + "-iport"), fetch(_fetch)
+        IcachePort(DefaultFetch<Impl> *_fetch, O3CPU *_cpu)
+            : Port(_fetch->name() + "-iport", _cpu), fetch(_fetch)
         { }
 
         bool snoopRangeSent;
index 7d344fa33208d58d60eeeb14d007f5ec1e8bb425..ecfbacd98f91a143dc119083e9c105eea0dc6532 100644 (file)
@@ -167,7 +167,7 @@ DefaultFetch<Impl>::DefaultFetch(O3CPU *_cpu, Params *params)
     instSize = sizeof(TheISA::MachInst);
 
     // Name is finally available, so create the port.
-    icachePort = new IcachePort(this);
+    icachePort = new IcachePort(this, cpu);
 
     icachePort->snoopRangeSent = false;
 
index 06de608e0b4e54afb61c9af75d8a886fbd415cc8..82d73c6ee2a32701e0c20c7081b0af94bd5be7b3 100644 (file)
@@ -296,8 +296,8 @@ class LSQ {
 
       public:
         /** Default constructor. */
-        DcachePort(LSQ *_lsq)
-            : Port(_lsq->name() + "-dport"), lsq(_lsq)
+        DcachePort(LSQ *_lsq, O3CPU *_cpu)
+            : Port(_lsq->name() + "-dport", _cpu), lsq(_lsq)
         { }
 
         bool snoopRangeSent;
index 8ed6f7f54766d20bbcee155afa821940389d4560..41ab66dd0753c68550cf0ba04801c2ed6c042261 100644 (file)
@@ -112,7 +112,7 @@ LSQ<Impl>::DcachePort::recvRetry()
 
 template <class Impl>
 LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params)
-    : cpu(cpu_ptr), iewStage(iew_ptr), dcachePort(this),
+    : cpu(cpu_ptr), iewStage(iew_ptr), dcachePort(this, cpu_ptr),
       LQEntries(params->LQEntries),
       SQEntries(params->SQEntries),
       numThreads(params->numberOfThreads),
index 865d5863528b46568f80abad62c051bf0e4b0f72..514d3de6412fa3b3ad613d0efa14bfe497097606 100755 (executable)
@@ -103,7 +103,6 @@ void
 O3ThreadContext<Impl>::delVirtPort(VirtualPort *vp)
 {
     if (vp != thread->getVirtPort()) {
-        vp->removeConn();
         delete vp;
     }
 }
index 0c7105382c54bd6abf51b5999de79233273a2794..4cb55fa234550fe5770e93a1e4fe39916fa7a28a 100644 (file)
@@ -747,7 +747,6 @@ template <class Impl>
 void
 OzoneCPU<Impl>::OzoneTC::delVirtPort(VirtualPort *vp)
 {
-    vp->removeConn();
     delete vp;
 }
 #endif
index 5a5444de413617386bb5b9e9cb3cb36971ad140f..47b69d05fa5a52c4c4ee25d0afb813f67fd92d1f 100644 (file)
@@ -302,7 +302,6 @@ void
 SimpleThread::delVirtPort(VirtualPort *vp)
 {
     if (vp != virtPort) {
-        vp->removeConn();
         delete vp;
     }
 }
index bcfc9c924f077437668a605400ff0d7925422a57..56839ca7f343bdc700c9c302d6cc04487590111e 100644 (file)
@@ -126,7 +126,7 @@ ThreadState::connectPhysPort()
     // already existed.  Fix this memory leak once the bus port IDs
     // for functional ports is resolved.
     if (physPort)
-        physPort->removeConn();
+        physPort->disconnectFromPeer();
     else
         physPort = new FunctionalPort(csprintf("%s-%d-funcport",
                                            baseCpu->name(), tid));
@@ -140,7 +140,7 @@ ThreadState::connectVirtPort()
     // already existed.  Fix this memory leak once the bus port IDs
     // for functional ports is resolved.
     if (virtPort)
-        virtPort->removeConn();
+        virtPort->disconnectFromPeer();
     else
         virtPort = new VirtualPort(csprintf("%s-%d-vport",
                                         baseCpu->name(), tid));
index c09cacc00c78e9247539253b5715951923ea36b7..25c6e5d197ad5cc2eb705f283a5eb033ceb11ecf 100644 (file)
@@ -47,7 +47,7 @@ Bridge::BridgePort::BridgePort(const std::string &_name,
                                int _delay, int _nack_delay, int _req_limit,
                                int _resp_limit,
                                std::vector<Range<Addr> > filter_ranges)
-    : Port(_name), bridge(_bridge), otherPort(_otherPort),
+    : Port(_name, _bridge), bridge(_bridge), otherPort(_otherPort),
       delay(_delay), nackDelay(_nack_delay), filterRanges(filter_ranges),
       outstandingResponses(0), queuedRequests(0), inRetry(false),
       reqQueueLimit(_req_limit), respQueueLimit(_resp_limit), sendEvent(this)
index 3bf1c6cfc5f0f9e255574b028a4499009354b427..9dd3353fda9340570e711ca59b5acbf6bc7e081e 100644 (file)
@@ -72,8 +72,8 @@ Bus::getPort(const std::string &if_name, int idx)
     return bp;
 }
 
-void
-Bus::deletePortRefs(Port *p)
+bool
+Bus::deletePort(Port *p)
 {
 
     BusPort *bp =  dynamic_cast<BusPort*>(p);
@@ -81,10 +81,11 @@ Bus::deletePortRefs(Port *p)
         panic("Couldn't convert Port* to BusPort*\n");
     // If this is our one functional port
     if (funcPort == bp)
-        return;
+        return false;
     interfaces.erase(bp->getId());
     clearBusCache();
     delete bp;
+    return true;
 }
 
 /** Get the ranges of anyone other buses that we are connected to. */
index 74901d6268dac9a9c69823e15e605ec58b0e31ff..7d476bb65a37bf78f9c954802640bf98d1ce797a 100644 (file)
@@ -364,7 +364,7 @@ class Bus : public MemObject
 
     /** A function used to return the port associated with this bus object. */
     virtual Port *getPort(const std::string &if_name, int idx = -1);
-    virtual void deletePortRefs(Port *p);
+    virtual bool deletePort(Port *p);
 
     virtual void init();
     virtual void startup();
index 88c9deb7bab4c701f25813bf8b972e580845c6aa..56ae811a3cee547f35aa62ee6db510c8e620edfd 100644 (file)
@@ -217,7 +217,7 @@ class Cache : public BaseCache
     Cache(const Params *p, TagStore *tags, BasePrefetcher *prefetcher);
 
     virtual Port *getPort(const std::string &if_name, int idx = -1);
-    virtual void deletePortRefs(Port *p);
+    virtual bool deletePort(Port *p);
 
     void regStats();
 
index 3b56c0a2e3967438cd569e1aa64975b9c3c3e130..a3dae7b2a249441ae386ab0acb0bb9e0c51b5e6b 100644 (file)
@@ -105,13 +105,14 @@ Cache<TagStore>::getPort(const std::string &if_name, int idx)
 }
 
 template<class TagStore>
-void
-Cache<TagStore>::deletePortRefs(Port *p)
+bool
+Cache<TagStore>::deletePort(Port *p)
 {
     if (cpuSidePort == p || memSidePort == p)
         panic("Can only delete functional ports\n");
 
     delete p;
+    return true;
 }
 
 
index ce2a1107e6a7f52a9425aedf187cbc3bccbbd461..7d27db7637afeda4434d06fd2df37c31c6f16bbc 100644 (file)
@@ -43,8 +43,8 @@ MemObject::makeParams(const std::string &name)
     return params;
 }
 
-void
-MemObject::deletePortRefs(Port *p)
+bool
+MemObject::deletePort(Port *p)
 {
     panic("This object does not support port deletion\n");
 }
index 33b56dfd4094c9637b262fe96c1c8bf3a9abfb44..a91ea5ac4accd71b93704fe45687b7494a6cf31e 100644 (file)
@@ -64,9 +64,13 @@ class MemObject : public SimObject
     /** Additional function to return the Port of a memory object. */
     virtual Port *getPort(const std::string &if_name, int idx = -1) = 0;
 
-    /** Tell object that this port is about to disappear, so it should remove it
-     * from any structures that it's keeping it in. */
-    virtual void deletePortRefs(Port *p) ;
+    /** Tell MemObject that this port is no longer in use, so it
+     * should remove it from any structures that it's keeping it in.
+     * If the port was allocated dynamically for this connection, it
+     * should be deleted here.
+     * @return True if the port was deleted, false if it still exists.
+     */
+    virtual bool deletePort(Port *p);
 };
 
 #endif //__MEM_MEM_OBJECT_HH__
index 0e03194c9b2a439854355e13caed9c35b36c5687..1e6989750f12f9625ccb2117044765f70be23d80 100644 (file)
 #include "mem/mem_object.hh"
 #include "mem/port.hh"
 
+/**
+ * Special class for port objects that are used as peers for
+ * unconnected ports.  Assigning instances of this class to newly
+ * allocated ports allows us to guarantee that every port has a peer
+ * object (so there's no need to check for null peer pointers), while
+ * catching uses of unconnected ports.
+ */
 class DefaultPeerPort : public Port
 {
   protected:
     void blowUp()
     {
-        fatal("%s: Unconnected port!", peer->name());
+        Port *peer = getPeer();
+        fatal("unconnected port: %s", peer ? peer->name() : "<unknown>");
     }
 
   public:
-    DefaultPeerPort()
-        : Port("default_port")
+    DefaultPeerPort(Port *_peer)
+        : Port("default_port", NULL, _peer)
     { }
 
     bool recvTiming(PacketPtr)
@@ -88,36 +96,59 @@ class DefaultPeerPort : public Port
     bool isDefaultPort() const { return true; }
 };
 
-DefaultPeerPort defaultPeerPort;
 
-Port::Port()
-    : peer(&defaultPeerPort), owner(NULL)
+Port::Port(const std::string &_name, MemObject *_owner, Port *_peer) :
+    portName(_name),
+    peer(_peer ? _peer : new DefaultPeerPort(this)),
+    owner(_owner)
 {
 }
 
-Port::Port(const std::string &_name, MemObject *_owner)
-    : portName(_name), peer(&defaultPeerPort), owner(_owner)
+Port::~Port()
 {
+    disconnectFromPeer();
 }
 
-Port::~Port()
+void
+Port::disconnectFromPeer()
 {
+    if (peer) {
+        assert(peer->getPeer() == this);
+        peer->disconnect();
+    }
 }
 
 void
-Port::setPeer(Port *port)
+Port::disconnect()
 {
-    DPRINTF(Config, "setting peer to %s\n", port->name());
-
-    peer = port;
+    // This notification should come only from our peer, so we must
+    // have one,
+    assert(peer != NULL);
+    // We must clear 'peer' here, else if owner->deletePort() calls
+    // delete on us then we'll recurse infinitely through the Port
+    // destructor.
+    peer = NULL;
+    // If owner->deletePort() returns true, then we've been deleted,
+    // so don't do anything but get out of here.  If not, reset peer
+    // pointer to a DefaultPeerPort.
+    if (!(owner && owner->deletePort(this)))
+        peer = new DefaultPeerPort(this);
 }
 
 void
-Port::removeConn()
+Port::setPeer(Port *port)
 {
-    if (peer->getOwner())
-        peer->getOwner()->deletePortRefs(peer);
-    peer = NULL;
+    DPRINTF(Config, "setting peer to %s, old peer %s\n",
+            port->name(), peer ? peer->name() : "<null>");
+    
+    // You'd think we'd want to disconnect from the previous peer
+    // here, but it turns out that with some functional ports the old
+    // peer keeps using the connection, and it works because
+    // functional ports are unidirectional.
+    //
+    // disconnectFromPeer();
+
+    peer = port;
 }
 
 void
index 15fda21644aacf7ba7aaa5c0afa91784298c3660..4e0d91e756f446dfabdcd9b45ee2ba93cd8def73 100644 (file)
@@ -87,17 +87,14 @@ class Port
 
   public:
 
-    Port();
-
     /**
      * Constructor.
      *
      * @param _name Port name for DPRINTF output.  Should include name
      * of memory system object to which the port belongs.
      * @param _owner Pointer to the MemObject that owns this port.
-     * Will not necessarily be set.
      */
-    Port(const std::string &_name, MemObject *_owner = NULL);
+    Port(const std::string &_name, MemObject *_owner, Port *_peer = NULL);
 
     /** Return port name (for DPRINTF). */
     const std::string &name() const { return portName; }
@@ -111,24 +108,18 @@ class Port
         RangeChange
     };
 
-    void setName(const std::string &name)
-    { portName = name; }
-
     /** Function to set the pointer for the peer port. */
     virtual void setPeer(Port *port);
 
     /** Function to get the pointer to the peer port. */
     Port *getPeer() { return peer; }
 
-    /** Function to set the owner of this port. */
-    void setOwner(MemObject *_owner) { owner = _owner; }
-
     /** Function to return the owner of this port. */
     MemObject *getOwner() { return owner; }
 
-    /** Inform the peer port to delete itself and notify it's owner about it's
-     * demise. */
-    void removeConn();
+    /** Notify my peer port that I'm disconnecting (by calling its
+     * disconnect() method) so it can clean up. */
+    void disconnectFromPeer();
 
     virtual bool isDefaultPort() const { return false; }
 
@@ -254,6 +245,11 @@ class Port
     /** Internal helper function for read/writeBlob().
      */
     void blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd);
+
+    /** Receive notification that my peer is disconnecting and clean
+     * up (potentially deleting myself in the process). Should be
+     * called only from peer's disconnectFromPeer(). */
+    void disconnect();
 };
 
 /** A simple functional port that is only meant for one way communication to