Move PioPort timing code into Simple Timing Port object
authorAli Saidi <saidi@eecs.umich.edu>
Thu, 20 Jul 2006 23:03:47 +0000 (19:03 -0400)
committerAli Saidi <saidi@eecs.umich.edu>
Thu, 20 Jul 2006 23:03:47 +0000 (19:03 -0400)
Make PioPort use it
Make Physical memory use it as well

src/SConscript:
    Add timing port to sconscript
src/dev/io_device.cc:
src/dev/io_device.hh:
    Move simple timing pio port stuff into a simple timing port class so it can be used by the physical memory
src/mem/physical.cc:
src/mem/physical.hh:
    use a simple timing port stuff instead of rolling our own here

--HG--
extra : convert_revision : e5befbd295a572568cfdca533efb5ed1984c59d1

src/SConscript
src/dev/io_device.cc
src/dev/io_device.hh
src/mem/physical.cc
src/mem/physical.hh
src/mem/tport.cc [new file with mode: 0644]
src/mem/tport.hh [new file with mode: 0644]

index 9825cafe7bf8923e516c9dfb93f92299a8ddf18e..5e61b285b80e5d1181c8a6d3c01cfc2844752c8a 100644 (file)
@@ -98,6 +98,7 @@ base_sources = Split('''
         mem/packet.cc
         mem/physical.cc
         mem/port.cc
+        mem/tport.cc
 
         mem/cache/base_cache.cc
         mem/cache/cache.cc
index 660efabfde71cf13e205c9624548a213c58d9f52..b51a931902f4c8808e6f9866bd43161d5980f541 100644 (file)
@@ -36,8 +36,7 @@
 
 
 PioPort::PioPort(PioDevice *dev, System *s, std::string pname)
-    : Port(dev->name() + pname), device(dev), sys(s),
-      outTiming(0), drainEvent(NULL)
+    : SimpleTimingPort(dev->name() + pname), device(dev), sys(s)
 { }
 
 
@@ -61,48 +60,6 @@ PioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
 }
 
 
-void
-PioPort::recvRetry()
-{
-    bool result = true;
-    while (result && transmitList.size()) {
-        result = Port::sendTiming(transmitList.front());
-        if (result)
-            transmitList.pop_front();
-    }
-   if (transmitList.size() == 0 && drainEvent) {
-       drainEvent->process();
-       drainEvent = NULL;
-   }
-}
-
-void
-PioPort::SendEvent::process()
-{
-    port->outTiming--;
-    assert(port->outTiming >= 0);
-    if (port->Port::sendTiming(packet))
-       if (port->transmitList.size() == 0 && port->drainEvent) {
-           port->drainEvent->process();
-           port->drainEvent = NULL;
-       }
-       return;
-
-    port->transmitList.push_back(packet);
-}
-
-void
-PioPort::resendNacked(Packet *pkt) {
-    pkt->reinitNacked();
-    if (transmitList.size()) {
-         transmitList.push_front(pkt);
-    } else {
-        if (!Port::sendTiming(pkt))
-            transmitList.push_front(pkt);
-    }
-};
-
-
 bool
 PioPort::recvTiming(Packet *pkt)
 {
@@ -117,15 +74,6 @@ PioPort::recvTiming(Packet *pkt)
     return true;
 }
 
-unsigned int
-PioPort::drain(Event *de)
-{
-    if (outTiming == 0 && transmitList.size() == 0)
-        return 0;
-    drainEvent = de;
-    return 1;
-}
-
 PioDevice::~PioDevice()
 {
     if (pioPort)
index fa3f982476b106c6459b88ec450be5ea1af7d68d..22a32e73ae2960ae9eb691b5289ce4adf7d45987 100644 (file)
@@ -37,6 +37,7 @@
 #include "mem/packet_impl.hh"
 #include "sim/eventq.hh"
 #include "sim/sim_object.hh"
+#include "mem/tport.hh"
 
 class Platform;
 class PioDevice;
@@ -48,13 +49,9 @@ class System;
  * sensitive to an address range use. The port takes all the memory
  * access types and roles them into one read() and write() call that the device
  * must respond to. The device must also provide the addressRanges() function
- * with which it returns the address ranges it is interested in. An extra
- * sendTiming() function is implemented which takes an delay. In this way the
- * device can immediatly call sendTiming(pkt, time) after processing a request
- * and the request will be handled by the port even if the port bus the device
- * connects to is blocked.
- */
-class PioPort : public Port
+ * with which it returns the address ranges it is interested in. */
+
+class PioPort : public SimpleTimingPort
 {
   protected:
     /** The device that this port serves. */
@@ -64,10 +61,6 @@ class PioPort : public Port
      * we are currently operating in. */
     System *sys;
 
-    /** A list of outgoing timing response packets that haven't been serviced
-     * yet. */
-    std::list<Packet*> transmitList;
-
     /** The current status of the peer(bus) that we are connected to. */
     Status peerStatus;
 
@@ -82,53 +75,9 @@ class PioPort : public Port
 
     virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
 
-    void resendNacked(Packet *pkt);
-
-    /**
-     * This class is used to implemented sendTiming() with a delay. When a delay
-     * is requested a new event is created. When the event time expires it
-     * attempts to send the packet. If it cannot, the packet is pushed onto the
-     * transmit list to be sent when recvRetry() is called. */
-    class SendEvent : public Event
-    {
-        PioPort *port;
-        Packet *packet;
-
-        SendEvent(PioPort *p, Packet *pkt, Tick t)
-            : Event(&mainEventQueue), port(p), packet(pkt)
-        { schedule(curTick + t); }
-
-        virtual void process();
-
-        virtual const char *description()
-        { return "Future scheduled sendTiming event"; }
-
-        friend class PioPort;
-    };
-
-    /** Number of timing requests that are emulating the device timing before
-     * attempting to end up on the bus.
-     */
-    int outTiming;
-
-    /** If we need to drain, keep the drain event around until we're done
-     * here.*/
-    Event *drainEvent;
-
-    /** Schedule a sendTiming() event to be called in the future. */
-    void sendTiming(Packet *pkt, Tick time)
-    { outTiming++; new PioPort::SendEvent(this, pkt, time); }
-
-    /** This function is notification that the device should attempt to send a
-     * packet again. */
-    virtual void recvRetry();
-
   public:
     PioPort(PioDevice *dev, System *s, std::string pname = "-pioport");
 
-    unsigned int drain(Event *de);
-
-  friend class PioPort::SendEvent;
 };
 
 
index 2d66602ab480fcded1a3756940799ee9458a0808..291c70d8c456b69a990a4fd56dff7fea850dc5dd 100644 (file)
@@ -26,6 +26,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Ron Dreslinski
+ *          Ali Saidi
  */
 
 #include <sys/types.h>
 using namespace std;
 using namespace TheISA;
 
-PhysicalMemory::MemResponseEvent::MemResponseEvent(Packet *pkt, MemoryPort* _m)
-    : Event(&mainEventQueue, CPU_Tick_Pri), pkt(pkt), memoryPort(_m)
-{
-
-    this->setFlags(AutoDelete);
-}
-
-void
-PhysicalMemory::MemResponseEvent::process()
-{
-    memoryPort->sendTiming(pkt);
-}
-
-const char *
-PhysicalMemory::MemResponseEvent::description()
-{
-    return "Physical Memory Timing Access respnse event";
-}
 
 PhysicalMemory::PhysicalMemory(const string &n, Tick latency)
     : MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency)
@@ -124,27 +107,8 @@ PhysicalMemory::deviceBlockSize()
     return 0;
 }
 
-bool
-PhysicalMemory::doTimingAccess (Packet *pkt, MemoryPort* memoryPort)
-{
-    doFunctionalAccess(pkt);
-
-    // turn packet around to go back to requester
-    pkt->makeTimingResponse();
-    MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort);
-    response->schedule(curTick + lat);
-
-    return true;
-}
 
 Tick
-PhysicalMemory::doAtomicAccess(Packet *pkt)
-{
-    doFunctionalAccess(pkt);
-    return lat;
-}
-
-void
 PhysicalMemory::doFunctionalAccess(Packet *pkt)
 {
     assert(pkt->getAddr() + pkt->getSize() < pmem_size);
@@ -170,6 +134,7 @@ PhysicalMemory::doFunctionalAccess(Packet *pkt)
     }
 
     pkt->result = Packet::Success;
+    return lat;
 }
 
 Port *
@@ -195,7 +160,7 @@ PhysicalMemory::recvStatusChange(Port::Status status)
 
 PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
                                        PhysicalMemory *_memory)
-    : Port(_name), memory(_memory)
+    : SimpleTimingPort(_name), memory(_memory)
 { }
 
 void
@@ -228,13 +193,20 @@ PhysicalMemory::MemoryPort::deviceBlockSize()
 bool
 PhysicalMemory::MemoryPort::recvTiming(Packet *pkt)
 {
-    return memory->doTimingAccess(pkt, this);
+    assert(pkt->result != Packet::Nacked);
+
+    Tick latency = memory->doFunctionalAccess(pkt);
+
+    pkt->makeTimingResponse();
+    sendTiming(pkt, latency);
+
+    return true;
 }
 
 Tick
 PhysicalMemory::MemoryPort::recvAtomic(Packet *pkt)
 {
-    return memory->doAtomicAccess(pkt);
+    return memory->doFunctionalAccess(pkt);
 }
 
 void
@@ -243,7 +215,16 @@ PhysicalMemory::MemoryPort::recvFunctional(Packet *pkt)
     memory->doFunctionalAccess(pkt);
 }
 
-
+unsigned int
+PhysicalMemory::drain(Event *de)
+{
+    int count = port->drain(de);
+    if (count)
+        changeState(Draining);
+    else
+        changeState(Drained);
+    return count;
+}
 
 void
 PhysicalMemory::serialize(ostream &os)
index 50fa75ed3e865ec9803faab421419ab6fc3ae21b..b549c1f8bc48537db0db83b00c90b47fc7eb5bba 100644 (file)
@@ -37,7 +37,7 @@
 #include "base/range.hh"
 #include "mem/mem_object.hh"
 #include "mem/packet.hh"
-#include "mem/port.hh"
+#include "mem/tport.hh"
 #include "sim/eventq.hh"
 #include <map>
 #include <string>
@@ -47,7 +47,7 @@
 //
 class PhysicalMemory : public MemObject
 {
-    class MemoryPort : public Port
+    class MemoryPort : public SimpleTimingPort
     {
         PhysicalMemory *memory;
 
@@ -74,16 +74,6 @@ class PhysicalMemory : public MemObject
     int numPorts;
 
 
-    struct MemResponseEvent : public Event
-    {
-        Packet *pkt;
-        MemoryPort *memoryPort;
-
-        MemResponseEvent(Packet *pkt, MemoryPort *memoryPort);
-        void process();
-        const char *description();
-    };
-
   private:
     // prevent copying of a MainMemory object
     PhysicalMemory(const PhysicalMemory &specmem);
@@ -110,13 +100,10 @@ class PhysicalMemory : public MemObject
     void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
     virtual Port *getPort(const std::string &if_name, int idx = -1);
     void virtual init();
+    unsigned int drain(Event *de);
 
-    // fast back-door memory access for vtophys(), remote gdb, etc.
-    // uint64_t phys_read_qword(Addr addr) const;
   private:
-    bool doTimingAccess(Packet *pkt, MemoryPort *memoryPort);
-    Tick doAtomicAccess(Packet *pkt);
-    void doFunctionalAccess(Packet *pkt);
+    Tick doFunctionalAccess(Packet *pkt);
 
     void recvStatusChange(Port::Status status);
 
diff --git a/src/mem/tport.cc b/src/mem/tport.cc
new file mode 100644 (file)
index 0000000..90cf68f
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ */
+
+#include "mem/tport.hh"
+
+void
+SimpleTimingPort::recvRetry()
+{
+    bool result = true;
+    while (result && transmitList.size()) {
+        result = Port::sendTiming(transmitList.front());
+        if (result)
+            transmitList.pop_front();
+    }
+   if (transmitList.size() == 0 && drainEvent) {
+       drainEvent->process();
+       drainEvent = NULL;
+   }
+}
+
+void
+SimpleTimingPort::SendEvent::process()
+{
+    port->outTiming--;
+    assert(port->outTiming >= 0);
+    if (port->Port::sendTiming(packet))
+       if (port->transmitList.size() == 0 && port->drainEvent) {
+           port->drainEvent->process();
+           port->drainEvent = NULL;
+       }
+       return;
+
+    port->transmitList.push_back(packet);
+}
+
+void
+SimpleTimingPort::resendNacked(Packet *pkt) {
+    pkt->reinitNacked();
+    if (transmitList.size()) {
+         transmitList.push_front(pkt);
+    } else {
+        if (!Port::sendTiming(pkt))
+            transmitList.push_front(pkt);
+    }
+};
+
+
+unsigned int
+SimpleTimingPort::drain(Event *de)
+{
+    if (outTiming == 0 && transmitList.size() == 0)
+        return 0;
+    drainEvent = de;
+    return 1;
+}
diff --git a/src/mem/tport.hh b/src/mem/tport.hh
new file mode 100644 (file)
index 0000000..5473e94
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ */
+
+/**
+ * @file
+ * Implement a port which adds simple support of a sendTiming() function that
+ * takes a delay. In this way the * device can immediatly call
+ * sendTiming(pkt, time) after processing a request and the request will be
+ * handled by the port even if the port bus the device connects to is blocked.
+ */
+
+/** recvTiming and drain should be implemented something like this when this
+ * class is used.
+
+bool
+PioPort::recvTiming(Packet *pkt)
+{
+    if (pkt->result == Packet::Nacked) {
+        resendNacked(pkt);
+    } else {
+        Tick latency = device->recvAtomic(pkt);
+        // turn packet around to go back to requester
+        pkt->makeTimingResponse();
+        sendTiming(pkt, latency);
+    }
+    return true;
+}
+
+PioDevice::drain(Event *de)
+{
+    unsigned int count;
+    count = SimpleTimingPort->drain(de);
+    if (count)
+        changeState(Draining);
+    else
+        changeState(Drained);
+    return count;
+}
+*/
+
+#ifndef __MEM_TPORT_HH__
+#define __MEM_TPORT_HH__
+
+#include "mem/port.hh"
+#include "sim/eventq.hh"
+#include <list>
+#include <string>
+
+class SimpleTimingPort : public Port
+{
+  protected:
+    /** A list of outgoing timing response packets that haven't been serviced
+     * yet. */
+    std::list<Packet*> transmitList;
+    /**
+     * This class is used to implemented sendTiming() with a delay. When a delay
+     * is requested a new event is created. When the event time expires it
+     * attempts to send the packet. If it cannot, the packet is pushed onto the
+     * transmit list to be sent when recvRetry() is called. */
+    class SendEvent : public Event
+    {
+        SimpleTimingPort *port;
+        Packet *packet;
+
+        SendEvent(SimpleTimingPort *p, Packet *pkt, Tick t)
+            : Event(&mainEventQueue), port(p), packet(pkt)
+        { setFlags(AutoDelete); schedule(curTick + t); }
+
+        virtual void process();
+
+        virtual const char *description()
+        { return "Future scheduled sendTiming event"; }
+
+        friend class SimpleTimingPort;
+    };
+
+
+    /** Number of timing requests that are emulating the device timing before
+     * attempting to end up on the bus.
+     */
+    int outTiming;
+
+    /** If we need to drain, keep the drain event around until we're done
+     * here.*/
+    Event *drainEvent;
+
+    /** Schedule a sendTiming() event to be called in the future. */
+    void sendTiming(Packet *pkt, Tick time)
+    { outTiming++; new SimpleTimingPort::SendEvent(this, pkt, time); }
+
+    /** This function is notification that the device should attempt to send a
+     * packet again. */
+    virtual void recvRetry();
+
+    void resendNacked(Packet *pkt);
+  public:
+
+    SimpleTimingPort(std::string pname)
+        : Port(pname), outTiming(0), drainEvent(NULL)
+    {}
+
+    unsigned int drain(Event *de);
+
+    friend class SimpleTimingPort::SendEvent;
+};
+
+#endif // __MEM_TPORT_HH__