Merge zizzer.eecs.umich.edu:/z/m5/Bitkeeper/newmem
into zizzer.eecs.umich.edu:/z/stever/bk/newmem-py --HG-- extra : convert_revision : 36640569d33c4410320b8444bb572f408bf5edde
This commit is contained in:
commit
f0c05de9f9
11 changed files with 148 additions and 118 deletions
|
@ -106,11 +106,10 @@ AtomicSimpleCPU::CpuPort::recvStatusChange(Status status)
|
||||||
panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!");
|
panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!");
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet *
|
void
|
||||||
AtomicSimpleCPU::CpuPort::recvRetry()
|
AtomicSimpleCPU::CpuPort::recvRetry()
|
||||||
{
|
{
|
||||||
panic("AtomicSimpleCPU doesn't expect recvRetry callback!");
|
panic("AtomicSimpleCPU doesn't expect recvRetry callback!");
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU
|
||||||
|
|
||||||
virtual void recvStatusChange(Status status);
|
virtual void recvStatusChange(Status status);
|
||||||
|
|
||||||
virtual Packet *recvRetry();
|
virtual void recvRetry();
|
||||||
|
|
||||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||||
AddrRangeList &snoop)
|
AddrRangeList &snoop)
|
||||||
|
|
|
@ -419,17 +419,18 @@ TimingSimpleCPU::IcachePort::recvTiming(Packet *pkt)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet *
|
void
|
||||||
TimingSimpleCPU::IcachePort::recvRetry()
|
TimingSimpleCPU::IcachePort::recvRetry()
|
||||||
{
|
{
|
||||||
// we shouldn't get a retry unless we have a packet that we're
|
// we shouldn't get a retry unless we have a packet that we're
|
||||||
// waiting to transmit
|
// waiting to transmit
|
||||||
assert(cpu->ifetch_pkt != NULL);
|
assert(cpu->ifetch_pkt != NULL);
|
||||||
assert(cpu->_status == IcacheRetry);
|
assert(cpu->_status == IcacheRetry);
|
||||||
cpu->_status = IcacheWaitResponse;
|
|
||||||
Packet *tmp = cpu->ifetch_pkt;
|
Packet *tmp = cpu->ifetch_pkt;
|
||||||
|
if (sendTiming(tmp)) {
|
||||||
|
cpu->_status = IcacheWaitResponse;
|
||||||
cpu->ifetch_pkt = NULL;
|
cpu->ifetch_pkt = NULL;
|
||||||
return tmp;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -459,17 +460,18 @@ TimingSimpleCPU::DcachePort::recvTiming(Packet *pkt)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet *
|
void
|
||||||
TimingSimpleCPU::DcachePort::recvRetry()
|
TimingSimpleCPU::DcachePort::recvRetry()
|
||||||
{
|
{
|
||||||
// we shouldn't get a retry unless we have a packet that we're
|
// we shouldn't get a retry unless we have a packet that we're
|
||||||
// waiting to transmit
|
// waiting to transmit
|
||||||
assert(cpu->dcache_pkt != NULL);
|
assert(cpu->dcache_pkt != NULL);
|
||||||
assert(cpu->_status == DcacheRetry);
|
assert(cpu->_status == DcacheRetry);
|
||||||
cpu->_status = DcacheWaitResponse;
|
|
||||||
Packet *tmp = cpu->dcache_pkt;
|
Packet *tmp = cpu->dcache_pkt;
|
||||||
|
if (sendTiming(tmp)) {
|
||||||
|
cpu->_status = DcacheWaitResponse;
|
||||||
cpu->dcache_pkt = NULL;
|
cpu->dcache_pkt = NULL;
|
||||||
return tmp;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||||
|
|
||||||
virtual bool recvTiming(Packet *pkt);
|
virtual bool recvTiming(Packet *pkt);
|
||||||
|
|
||||||
virtual Packet *recvRetry();
|
virtual void recvRetry();
|
||||||
};
|
};
|
||||||
|
|
||||||
class DcachePort : public CpuPort
|
class DcachePort : public CpuPort
|
||||||
|
@ -115,7 +115,7 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||||
|
|
||||||
virtual bool recvTiming(Packet *pkt);
|
virtual bool recvTiming(Packet *pkt);
|
||||||
|
|
||||||
virtual Packet *recvRetry();
|
virtual void recvRetry();
|
||||||
};
|
};
|
||||||
|
|
||||||
IcachePort icachePort;
|
IcachePort icachePort;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "base/trace.hh"
|
||||||
#include "dev/io_device.hh"
|
#include "dev/io_device.hh"
|
||||||
#include "sim/builder.hh"
|
#include "sim/builder.hh"
|
||||||
|
|
||||||
|
@ -55,12 +56,13 @@ PioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Packet *
|
void
|
||||||
PioPort::recvRetry()
|
PioPort::recvRetry()
|
||||||
{
|
{
|
||||||
Packet* pkt = transmitList.front();
|
Packet* pkt = transmitList.front();
|
||||||
|
if (Port::sendTiming(pkt)) {
|
||||||
transmitList.pop_front();
|
transmitList.pop_front();
|
||||||
return pkt;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,6 +76,7 @@ PioPort::SendEvent::process()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PioPort::recvTiming(Packet *pkt)
|
PioPort::recvTiming(Packet *pkt)
|
||||||
{
|
{
|
||||||
|
@ -116,16 +119,20 @@ DmaPort::recvTiming(Packet *pkt)
|
||||||
{
|
{
|
||||||
if (pkt->senderState) {
|
if (pkt->senderState) {
|
||||||
DmaReqState *state;
|
DmaReqState *state;
|
||||||
|
DPRINTF(DMA, "Received response Packet %#x with senderState: %#x\n",
|
||||||
|
pkt, pkt->senderState);
|
||||||
state = dynamic_cast<DmaReqState*>(pkt->senderState);
|
state = dynamic_cast<DmaReqState*>(pkt->senderState);
|
||||||
state->completionEvent->schedule(pkt->time - pkt->req->getTime());
|
assert(state);
|
||||||
|
state->completionEvent->process();
|
||||||
delete pkt->req;
|
delete pkt->req;
|
||||||
delete pkt;
|
delete pkt;
|
||||||
} else {
|
} else {
|
||||||
|
DPRINTF(DMA, "Received response Packet %#x with no senderState\n", pkt);
|
||||||
delete pkt->req;
|
delete pkt->req;
|
||||||
delete pkt;
|
delete pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Packet::Success;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DmaDevice::DmaDevice(Params *p)
|
DmaDevice::DmaDevice(Params *p)
|
||||||
|
@ -133,20 +140,19 @@ DmaDevice::DmaDevice(Params *p)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void
|
void
|
||||||
DmaPort::SendEvent::process()
|
|
||||||
{
|
|
||||||
if (port->Port::sendTiming(packet))
|
|
||||||
return;
|
|
||||||
|
|
||||||
port->transmitList.push_back(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet *
|
|
||||||
DmaPort::recvRetry()
|
DmaPort::recvRetry()
|
||||||
{
|
{
|
||||||
Packet* pkt = transmitList.front();
|
Packet* pkt = transmitList.front();
|
||||||
|
DPRINTF(DMA, "Retry on Packet %#x with senderState: %#x\n",
|
||||||
|
pkt, pkt->senderState);
|
||||||
|
if (sendTiming(pkt)) {
|
||||||
|
DPRINTF(DMA, "-- Done\n");
|
||||||
transmitList.pop_front();
|
transmitList.pop_front();
|
||||||
return pkt;
|
pendingCount--;
|
||||||
|
assert(pendingCount >= 0);
|
||||||
|
} else {
|
||||||
|
DPRINTF(DMA, "-- Failed, queued\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -192,13 +198,22 @@ DmaPort::sendDma(Packet *pkt)
|
||||||
// switching actually work
|
// switching actually work
|
||||||
/* MemState state = device->platform->system->memState;
|
/* MemState state = device->platform->system->memState;
|
||||||
|
|
||||||
if (state == Timing) {
|
if (state == Timing) { */
|
||||||
if (!sendTiming(pkt))
|
DPRINTF(DMA, "Attempting to send Packet %#x with senderState: %#x\n",
|
||||||
transmitList.push_back(&packet);
|
pkt, pkt->senderState);
|
||||||
} else if (state == Atomic) {*/
|
if (!sendTiming(pkt)) {
|
||||||
|
transmitList.push_back(pkt);
|
||||||
|
DPRINTF(DMA, "-- Failed: queued\n");
|
||||||
|
} else {
|
||||||
|
DPRINTF(DMA, "-- Done\n");
|
||||||
|
pendingCount--;
|
||||||
|
assert(pendingCount >= 0);
|
||||||
|
}
|
||||||
|
/* } else if (state == Atomic) {
|
||||||
sendAtomic(pkt);
|
sendAtomic(pkt);
|
||||||
if (pkt->senderState) {
|
if (pkt->senderState) {
|
||||||
DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
|
DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
|
||||||
|
assert(state);
|
||||||
state->completionEvent->schedule(curTick + (pkt->time - pkt->req->getTime()) +1);
|
state->completionEvent->schedule(curTick + (pkt->time - pkt->req->getTime()) +1);
|
||||||
}
|
}
|
||||||
pendingCount--;
|
pendingCount--;
|
||||||
|
@ -206,7 +221,7 @@ DmaPort::sendDma(Packet *pkt)
|
||||||
delete pkt->req;
|
delete pkt->req;
|
||||||
delete pkt;
|
delete pkt;
|
||||||
|
|
||||||
/* } else if (state == Functional) {
|
} else if (state == Functional) {
|
||||||
sendFunctional(pkt);
|
sendFunctional(pkt);
|
||||||
// Is this correct???
|
// Is this correct???
|
||||||
completionEvent->schedule(pkt->req->responseTime - pkt->req->requestTime);
|
completionEvent->schedule(pkt->req->responseTime - pkt->req->requestTime);
|
||||||
|
|
|
@ -105,8 +105,9 @@ class PioPort : public Port
|
||||||
void sendTiming(Packet *pkt, Tick time)
|
void sendTiming(Packet *pkt, Tick time)
|
||||||
{ new PioPort::SendEvent(this, pkt, time); }
|
{ new PioPort::SendEvent(this, pkt, time); }
|
||||||
|
|
||||||
/** This function pops the last element off the transmit list and sends it.*/
|
/** This function is notification that the device should attempt to send a
|
||||||
virtual Packet *recvRetry();
|
* packet again. */
|
||||||
|
virtual void recvRetry();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PioPort(PioDevice *dev, Platform *p);
|
PioPort(PioDevice *dev, Platform *p);
|
||||||
|
@ -146,28 +147,11 @@ class DmaPort : public Port
|
||||||
virtual void recvStatusChange(Status status)
|
virtual void recvStatusChange(Status status)
|
||||||
{ ; }
|
{ ; }
|
||||||
|
|
||||||
virtual Packet *recvRetry() ;
|
virtual void recvRetry() ;
|
||||||
|
|
||||||
virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
|
virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
|
||||||
{ resp.clear(); snoop.clear(); }
|
{ resp.clear(); snoop.clear(); }
|
||||||
|
|
||||||
class SendEvent : public Event
|
|
||||||
{
|
|
||||||
DmaPort *port;
|
|
||||||
Packet *packet;
|
|
||||||
|
|
||||||
SendEvent(PioPort *p, Packet *pkt, Tick t)
|
|
||||||
: Event(&mainEventQueue), packet(pkt)
|
|
||||||
{ schedule(curTick + t); }
|
|
||||||
|
|
||||||
virtual void process();
|
|
||||||
|
|
||||||
virtual const char *description()
|
|
||||||
{ return "Future scheduled sendTiming event"; }
|
|
||||||
|
|
||||||
friend class DmaPort;
|
|
||||||
};
|
|
||||||
|
|
||||||
void sendDma(Packet *pkt);
|
void sendDma(Packet *pkt);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -178,8 +162,6 @@ class DmaPort : public Port
|
||||||
|
|
||||||
bool dmaPending() { return pendingCount > 0; }
|
bool dmaPending() { return pendingCount > 0; }
|
||||||
|
|
||||||
friend class DmaPort::SendEvent;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -90,19 +90,6 @@ Bridge::BridgePort::recvTiming(Packet *pkt)
|
||||||
DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n",
|
DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n",
|
||||||
pkt->getSrc(), pkt->getDest(), pkt->getAddr());
|
pkt->getSrc(), pkt->getDest(), pkt->getAddr());
|
||||||
|
|
||||||
if (pkt->isResponse()) {
|
|
||||||
// This is a response for a request we forwarded earlier. The
|
|
||||||
// corresponding PacketBuffer should be stored in the packet's
|
|
||||||
// senderState field.
|
|
||||||
PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState);
|
|
||||||
assert(buf != NULL);
|
|
||||||
// set up new packet dest & senderState based on values saved
|
|
||||||
// from original request
|
|
||||||
buf->fixResponse(pkt);
|
|
||||||
DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest());
|
|
||||||
delete buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
return otherPort->queueForSendTiming(pkt);
|
return otherPort->queueForSendTiming(pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,8 +100,25 @@ Bridge::BridgePort::queueForSendTiming(Packet *pkt)
|
||||||
if (queueFull())
|
if (queueFull())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (pkt->isResponse()) {
|
||||||
|
// This is a response for a request we forwarded earlier. The
|
||||||
|
// corresponding PacketBuffer should be stored in the packet's
|
||||||
|
// senderState field.
|
||||||
|
PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState);
|
||||||
|
assert(buf != NULL);
|
||||||
|
// set up new packet dest & senderState based on values saved
|
||||||
|
// from original request
|
||||||
|
buf->fixResponse(pkt);
|
||||||
|
DPRINTF(BusBridge, "restoring sender state: %#X, from packet buffer: %#X\n",
|
||||||
|
pkt->senderState, buf);
|
||||||
|
DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest());
|
||||||
|
delete buf;
|
||||||
|
}
|
||||||
|
|
||||||
Tick readyTime = curTick + delay;
|
Tick readyTime = curTick + delay;
|
||||||
PacketBuffer *buf = new PacketBuffer(pkt, readyTime);
|
PacketBuffer *buf = new PacketBuffer(pkt, readyTime);
|
||||||
|
DPRINTF(BusBridge, "old sender state: %#X, new sender state: %#X\n",
|
||||||
|
buf->origSenderState, buf);
|
||||||
|
|
||||||
// If we're about to put this packet at the head of the queue, we
|
// If we're about to put this packet at the head of the queue, we
|
||||||
// need to schedule an event to do the transmit. Otherwise there
|
// need to schedule an event to do the transmit. Otherwise there
|
||||||
|
@ -126,17 +130,30 @@ Bridge::BridgePort::queueForSendTiming(Packet *pkt)
|
||||||
|
|
||||||
sendQueue.push_back(buf);
|
sendQueue.push_back(buf);
|
||||||
|
|
||||||
// Did we just become blocked? If yes, let other side know.
|
|
||||||
if (queueFull())
|
|
||||||
otherPort->sendStatusChange(Port::Blocked);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Bridge::BridgePort::finishSend(PacketBuffer *buf)
|
Bridge::BridgePort::trySend()
|
||||||
{
|
{
|
||||||
|
assert(!sendQueue.empty());
|
||||||
|
|
||||||
|
bool was_full = queueFull();
|
||||||
|
|
||||||
|
PacketBuffer *buf = sendQueue.front();
|
||||||
|
|
||||||
|
assert(buf->ready <= curTick);
|
||||||
|
|
||||||
|
Packet *pkt = buf->pkt;
|
||||||
|
|
||||||
|
DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n",
|
||||||
|
buf->origSrc, pkt->getDest(), pkt->getAddr());
|
||||||
|
|
||||||
|
if (sendTiming(pkt)) {
|
||||||
|
// send successful
|
||||||
|
sendQueue.pop_front();
|
||||||
|
buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it
|
||||||
|
|
||||||
if (buf->expectResponse) {
|
if (buf->expectResponse) {
|
||||||
// Must wait for response. We just need to count outstanding
|
// Must wait for response. We just need to count outstanding
|
||||||
// responses (in case we want to cap them); PacketBuffer
|
// responses (in case we want to cap them); PacketBuffer
|
||||||
|
@ -155,41 +172,22 @@ Bridge::BridgePort::finishSend(PacketBuffer *buf)
|
||||||
buf = sendQueue.front();
|
buf = sendQueue.front();
|
||||||
sendEvent.schedule(std::max(buf->ready, curTick + 1));
|
sendEvent.schedule(std::max(buf->ready, curTick + 1));
|
||||||
}
|
}
|
||||||
|
// Let things start sending again
|
||||||
|
if (was_full) {
|
||||||
|
DPRINTF(BusBridge, "Queue was full, sending retry\n");
|
||||||
|
otherPort->sendRetry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Bridge::BridgePort::trySend()
|
|
||||||
{
|
|
||||||
assert(!sendQueue.empty());
|
|
||||||
|
|
||||||
PacketBuffer *buf = sendQueue.front();
|
|
||||||
|
|
||||||
assert(buf->ready <= curTick);
|
|
||||||
|
|
||||||
Packet *pkt = buf->pkt;
|
|
||||||
|
|
||||||
DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n",
|
|
||||||
buf->origSrc, pkt->getDest(), pkt->getAddr());
|
|
||||||
|
|
||||||
if (sendTiming(pkt)) {
|
|
||||||
// send successful
|
|
||||||
sendQueue.pop_front();
|
|
||||||
buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it
|
|
||||||
finishSend(buf);
|
|
||||||
} else {
|
} else {
|
||||||
DPRINTF(BusBridge, " unsuccessful\n");
|
DPRINTF(BusBridge, " unsuccessful\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Packet *
|
void
|
||||||
Bridge::BridgePort::recvRetry()
|
Bridge::BridgePort::recvRetry()
|
||||||
{
|
{
|
||||||
PacketBuffer *buf = sendQueue.front();
|
trySend();
|
||||||
Packet *pkt = buf->pkt;
|
|
||||||
finishSend(buf);
|
|
||||||
return pkt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Function called by the port when the bus is receiving a Atomic
|
/** Function called by the port when the bus is receiving a Atomic
|
||||||
|
@ -223,9 +221,6 @@ Bridge::BridgePort::recvFunctional(Packet *pkt)
|
||||||
void
|
void
|
||||||
Bridge::BridgePort::recvStatusChange(Port::Status status)
|
Bridge::BridgePort::recvStatusChange(Port::Status status)
|
||||||
{
|
{
|
||||||
if (status == Port::Blocked || status == Port::Unblocked)
|
|
||||||
return;
|
|
||||||
|
|
||||||
otherPort->sendStatusChange(status);
|
otherPort->sendStatusChange(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
|
||||||
#include "mem/mem_object.hh"
|
#include "mem/mem_object.hh"
|
||||||
#include "mem/packet.hh"
|
#include "mem/packet.hh"
|
||||||
#include "mem/port.hh"
|
#include "mem/port.hh"
|
||||||
|
@ -77,6 +76,7 @@ class Bridge : public MemObject
|
||||||
origSenderState(_pkt->senderState), origSrc(_pkt->getSrc()),
|
origSenderState(_pkt->senderState), origSrc(_pkt->getSrc()),
|
||||||
expectResponse(_pkt->needsResponse())
|
expectResponse(_pkt->needsResponse())
|
||||||
{
|
{
|
||||||
|
if (!pkt->isResponse())
|
||||||
pkt->senderState = this;
|
pkt->senderState = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ class Bridge : public MemObject
|
||||||
|
|
||||||
/** When receiving a retry request from the peer port,
|
/** When receiving a retry request from the peer port,
|
||||||
pass it to the bridge. */
|
pass it to the bridge. */
|
||||||
virtual Packet* recvRetry();
|
virtual void recvRetry();
|
||||||
|
|
||||||
/** When receiving a Atomic requestfrom the peer port,
|
/** When receiving a Atomic requestfrom the peer port,
|
||||||
pass it to the bridge. */
|
pass it to the bridge. */
|
||||||
|
|
|
@ -72,9 +72,35 @@ Bus::recvTiming(Packet *pkt)
|
||||||
assert(dest != pkt->getSrc()); // catch infinite loops
|
assert(dest != pkt->getSrc()); // catch infinite loops
|
||||||
port = interfaces[dest];
|
port = interfaces[dest];
|
||||||
}
|
}
|
||||||
return port->sendTiming(pkt);
|
if (port->sendTiming(pkt)) {
|
||||||
|
// packet was successfully sent, just return true.
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// packet not successfully sent
|
||||||
|
retryList.push_back(interfaces[pkt->getSrc()]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Bus::recvRetry(int id)
|
||||||
|
{
|
||||||
|
// Go through all the elements on the list calling sendRetry on each
|
||||||
|
// This is not very efficient at all but it works. Ultimately we should end
|
||||||
|
// up with something that is more intelligent.
|
||||||
|
int initialSize = retryList.size();
|
||||||
|
int i;
|
||||||
|
Port *p;
|
||||||
|
|
||||||
|
for (i = 0; i < initialSize; i++) {
|
||||||
|
assert(retryList.size() > 0);
|
||||||
|
p = retryList.front();
|
||||||
|
retryList.pop_front();
|
||||||
|
p->sendRetry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Port *
|
Port *
|
||||||
Bus::findPort(Addr addr, int id)
|
Bus::findPort(Addr addr, int id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,6 +67,10 @@ class Bus : public MemObject
|
||||||
transaction.*/
|
transaction.*/
|
||||||
void recvFunctional(Packet *pkt);
|
void recvFunctional(Packet *pkt);
|
||||||
|
|
||||||
|
/** Timing function called by port when it is once again able to process
|
||||||
|
* requests. */
|
||||||
|
void recvRetry(int id);
|
||||||
|
|
||||||
/** Function called by the port when the bus is recieving a status change.*/
|
/** Function called by the port when the bus is recieving a status change.*/
|
||||||
void recvStatusChange(Port::Status status, int id);
|
void recvStatusChange(Port::Status status, int id);
|
||||||
|
|
||||||
|
@ -126,6 +130,11 @@ class Bus : public MemObject
|
||||||
virtual void recvStatusChange(Status status)
|
virtual void recvStatusChange(Status status)
|
||||||
{ bus->recvStatusChange(status, id); }
|
{ bus->recvStatusChange(status, id); }
|
||||||
|
|
||||||
|
/** When reciving a retry from the peer port (at id),
|
||||||
|
pass it to the bus. */
|
||||||
|
virtual void recvRetry()
|
||||||
|
{ bus->recvRetry(id); }
|
||||||
|
|
||||||
// This should return all the 'owned' addresses that are
|
// This should return all the 'owned' addresses that are
|
||||||
// downstream from this bus, yes? That is, the union of all
|
// downstream from this bus, yes? That is, the union of all
|
||||||
// the 'owned' address ranges of all the other interfaces on
|
// the 'owned' address ranges of all the other interfaces on
|
||||||
|
@ -143,6 +152,10 @@ class Bus : public MemObject
|
||||||
connected to this bus.*/
|
connected to this bus.*/
|
||||||
std::vector<Port*> interfaces;
|
std::vector<Port*> interfaces;
|
||||||
|
|
||||||
|
/** An array of pointers to ports that retry should be called on because the
|
||||||
|
* original send failed for whatever reason.*/
|
||||||
|
std::list<Port*> retryList;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** A function used to return the port associated with this bus object. */
|
/** A function used to return the port associated with this bus object. */
|
||||||
|
|
|
@ -92,11 +92,9 @@ class Port
|
||||||
virtual ~Port() {};
|
virtual ~Port() {};
|
||||||
|
|
||||||
// mey be better to use subclasses & RTTI?
|
// mey be better to use subclasses & RTTI?
|
||||||
/** Holds the ports status. Keeps track if it is blocked, or has
|
/** Holds the ports status. Currently just that a range recomputation needs
|
||||||
calculated a range change. */
|
* to be done. */
|
||||||
enum Status {
|
enum Status {
|
||||||
Blocked,
|
|
||||||
Unblocked,
|
|
||||||
RangeChange
|
RangeChange
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -140,7 +138,7 @@ class Port
|
||||||
wait. This shouldn't be valid for response paths (IO Devices).
|
wait. This shouldn't be valid for response paths (IO Devices).
|
||||||
so it is set to panic if it isn't already defined.
|
so it is set to panic if it isn't already defined.
|
||||||
*/
|
*/
|
||||||
virtual Packet *recvRetry() { panic("??"); }
|
virtual void recvRetry() { panic("??"); }
|
||||||
|
|
||||||
/** Called by a peer port in order to determine the block size of the
|
/** Called by a peer port in order to determine the block size of the
|
||||||
device connected to this port. It sometimes doesn't make sense for
|
device connected to this port. It sometimes doesn't make sense for
|
||||||
|
@ -165,7 +163,7 @@ class Port
|
||||||
port receive function.
|
port receive function.
|
||||||
@return This function returns if the send was succesful in it's
|
@return This function returns if the send was succesful in it's
|
||||||
recieve. If it was a failure, then the port will wait for a recvRetry
|
recieve. If it was a failure, then the port will wait for a recvRetry
|
||||||
at which point it can issue a successful sendTiming. This is used in
|
at which point it can possibly issue a successful sendTiming. This is used in
|
||||||
case a cache has a higher priority request come in while waiting for
|
case a cache has a higher priority request come in while waiting for
|
||||||
the bus to arbitrate.
|
the bus to arbitrate.
|
||||||
*/
|
*/
|
||||||
|
@ -194,7 +192,7 @@ class Port
|
||||||
/** When a timing access doesn't return a success, some time later the
|
/** When a timing access doesn't return a success, some time later the
|
||||||
Retry will be sent.
|
Retry will be sent.
|
||||||
*/
|
*/
|
||||||
Packet *sendRetry() { return peer->recvRetry(); }
|
void sendRetry() { return peer->recvRetry(); }
|
||||||
|
|
||||||
/** Called by the associated device if it wishes to find out the blocksize
|
/** Called by the associated device if it wishes to find out the blocksize
|
||||||
of the device on attached to the peer port.
|
of the device on attached to the peer port.
|
||||||
|
|
Loading…
Reference in a new issue