summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/SConscript1
-rw-r--r--src/dev/io_device.cc54
-rw-r--r--src/dev/io_device.hh59
-rw-r--r--src/mem/physical.cc63
-rw-r--r--src/mem/physical.hh21
-rw-r--r--src/mem/tport.cc82
-rw-r--r--src/mem/tport.hh134
7 files changed, 248 insertions, 166 deletions
diff --git a/src/SConscript b/src/SConscript
index 9825cafe7..5e61b285b 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -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
diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc
index 660efabfd..b51a93190 100644
--- a/src/dev/io_device.cc
+++ b/src/dev/io_device.cc
@@ -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)
diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh
index fa3f98247..22a32e73a 100644
--- a/src/dev/io_device.hh
+++ b/src/dev/io_device.hh
@@ -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;
};
diff --git a/src/mem/physical.cc b/src/mem/physical.cc
index 2d66602ab..291c70d8c 100644
--- a/src/mem/physical.cc
+++ b/src/mem/physical.cc
@@ -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>
@@ -52,24 +53,6 @@
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)
diff --git a/src/mem/physical.hh b/src/mem/physical.hh
index 50fa75ed3..b549c1f8b 100644
--- a/src/mem/physical.hh
+++ b/src/mem/physical.hh
@@ -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
index 000000000..90cf68f02
--- /dev/null
+++ b/src/mem/tport.cc
@@ -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
index 000000000..5473e945e
--- /dev/null
+++ b/src/mem/tport.hh
@@ -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__