MEM: Simplify ports by removing EventManager

This patch removes the inheritance of EventManager from the ports and
moves all responsibility for event queues to the owner. Eventually the
event manager should be the interface block, which could either be the
structural owner or a subblock like a LSQ in the O3 CPU for example.
This commit is contained in:
Andreas Hansson
2012-01-17 12:55:09 -06:00
parent b3f930c884
commit de34e49d15
9 changed files with 42 additions and 36 deletions

View File

@@ -862,7 +862,7 @@ TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt)
// faster than a CPU we could get two responses before
// next_tick expires
if (!retryEvent.scheduled())
schedule(retryEvent, next_tick);
cpu->schedule(retryEvent, next_tick);
return false;
}
}

View File

@@ -136,7 +136,7 @@ DmaPort::recvTiming(PacketPtr pkt)
else if (backoffTime < maxBackoffDelay)
backoffTime <<= 1;
reschedule(backoffEvent, curTick() + backoffTime, true);
device->reschedule(backoffEvent, curTick() + backoffTime, true);
DPRINTF(DMA, "Backoff time set to %d ticks\n", backoffTime);
@@ -164,7 +164,8 @@ DmaPort::recvTiming(PacketPtr pkt)
if (state->totBytes == state->numBytes) {
if (state->completionEvent) {
if (state->delay)
schedule(state->completionEvent, curTick() + state->delay);
device->schedule(state->completionEvent,
curTick() + state->delay);
else
state->completionEvent->process();
}
@@ -234,7 +235,7 @@ DmaPort::recvRetry()
if (transmitList.size() && backoffTime && !inRetry) {
DPRINTF(DMA, "Scheduling backoff for %d\n", curTick()+backoffTime);
if (!backoffEvent.scheduled())
schedule(backoffEvent, backoffTime + curTick());
device->schedule(backoffEvent, backoffTime + curTick());
}
DPRINTF(DMA, "TransmitList: %d, backoffTime: %d inRetry: %d es: %d\n",
transmitList.size(), backoffTime, inRetry,
@@ -320,7 +321,7 @@ DmaPort::sendDma()
!backoffEvent.scheduled()) {
DPRINTF(DMA, "-- Scheduling backoff timer for %d\n",
backoffTime+curTick());
schedule(backoffEvent, backoffTime + curTick());
device->schedule(backoffEvent, backoffTime + curTick());
}
} else if (state == Enums::atomic) {
transmitList.pop_front();
@@ -342,7 +343,8 @@ DmaPort::sendDma()
if (state->totBytes == state->numBytes) {
if (state->completionEvent) {
assert(!state->completionEvent->scheduled());
schedule(state->completionEvent, curTick() + lat + state->delay);
device->schedule(state->completionEvent,
curTick() + lat + state->delay);
}
delete state;
delete pkt->req;

View File

@@ -165,7 +165,7 @@ Bridge::BridgePort::nackRequest(PacketPtr pkt)
// nothing on the list, add it and we're done
if (sendQueue.empty()) {
assert(!sendEvent.scheduled());
schedule(sendEvent, readyTime);
bridge->schedule(sendEvent, readyTime);
sendQueue.push_back(buf);
return;
}
@@ -187,7 +187,7 @@ Bridge::BridgePort::nackRequest(PacketPtr pkt)
while (i != end && !done) {
if (readyTime < (*i)->ready) {
if (i == begin)
reschedule(sendEvent, readyTime);
bridge->reschedule(sendEvent, readyTime);
sendQueue.insert(i,buf);
done = true;
}
@@ -230,7 +230,7 @@ Bridge::BridgePort::queueForSendTiming(PacketPtr pkt)
// should already be an event scheduled for sending the head
// packet.
if (sendQueue.empty()) {
schedule(sendEvent, readyTime);
bridge->schedule(sendEvent, readyTime);
}
sendQueue.push_back(buf);
}
@@ -284,7 +284,7 @@ Bridge::BridgePort::trySend()
if (!sendQueue.empty()) {
buf = sendQueue.front();
DPRINTF(BusBridge, "Scheduling next send\n");
schedule(sendEvent, std::max(buf->ready, curTick() + 1));
bridge->schedule(sendEvent, std::max(buf->ready, curTick() + 1));
}
} else {
DPRINTF(BusBridge, " unsuccessful\n");
@@ -305,7 +305,7 @@ Bridge::BridgePort::recvRetry()
if (nextReady <= curTick())
trySend();
else
schedule(sendEvent, nextReady);
bridge->schedule(sendEvent, nextReady);
}
/** Function called by the port when the bus is receiving a Atomic

View File

@@ -126,7 +126,7 @@ BaseCache::CachePort::clearBlocked()
mustSendRetry = false;
SendRetryEvent *ev = new SendRetryEvent(this, true);
// @TODO: need to find a better time (next bus cycle?)
schedule(ev, curTick() + 1);
cache->schedule(ev, curTick() + 1);
}
}

View File

@@ -1729,7 +1729,7 @@ Cache<TagStore>::MemSidePort::sendPacket()
// @TODO: need to facotr in prefetch requests here somehow
if (nextReady != MaxTick) {
DPRINTF(CachePort, "more packets to send @ %d\n", nextReady);
schedule(sendEvent, std::max(nextReady, curTick() + 1));
cache->schedule(sendEvent, std::max(nextReady, curTick() + 1));
} else {
// no more to send right now: if we're draining, we may be done
if (drainEvent && !sendEvent->scheduled()) {

View File

@@ -93,8 +93,7 @@ class DefaultPeerPort : public Port
DefaultPeerPort defaultPeerPort;
Port::Port(const std::string &_name, MemObject *_owner)
: EventManager(_owner), portName(_name), peer(&defaultPeerPort),
owner(_owner)
: portName(_name), peer(&defaultPeerPort), owner(_owner)
{
}
@@ -113,7 +112,6 @@ Port::setPeer(Port *port)
void
Port::setOwner(MemObject *_owner)
{
eventq = _owner->queue();
owner = _owner;
}

View File

@@ -47,7 +47,6 @@
#include "base/types.hh"
#include "mem/packet.hh"
#include "mem/request.hh"
#include "sim/eventq.hh"
/** This typedef is used to clean up the parameter list of
* getDeviceAddressRanges() and getPeerAddressRanges(). It's declared
@@ -59,7 +58,6 @@
typedef std::list<Range<Addr> > AddrRangeList;
typedef std::list<Range<Addr> >::iterator AddrRangeIter;
class EventQueue;
class MemObject;
/**
@@ -73,7 +71,7 @@ class MemObject;
* Send accessor functions are being called from the device the port is
* associated with, and it will call the peer recv. accessor function.
*/
class Port : public EventManager
class Port
{
protected:
/** Descriptive name (for DPRINTF output) */

View File

@@ -29,12 +29,13 @@
*/
#include "debug/Bus.hh"
#include "mem/mem_object.hh"
#include "mem/tport.hh"
using namespace std;
SimpleTimingPort::SimpleTimingPort(string pname, MemObject *_owner)
: Port(pname, _owner), sendEvent(0), drainEvent(NULL),
: Port(pname, _owner), sendEvent(NULL), drainEvent(NULL),
waitingOnRetry(false)
{
sendEvent = new EventWrapper<SimpleTimingPort,
@@ -104,6 +105,20 @@ SimpleTimingPort::recvTiming(PacketPtr pkt)
return true;
}
void
SimpleTimingPort::schedSendEvent(Tick when)
{
if (waitingOnRetry) {
assert(!sendEvent->scheduled());
return;
}
if (!sendEvent->scheduled()) {
owner->schedule(sendEvent, when);
} else if (sendEvent->when() > when) {
owner->reschedule(sendEvent, when);
}
}
void
SimpleTimingPort::schedSendTiming(PacketPtr pkt, Tick when)
@@ -153,7 +168,7 @@ SimpleTimingPort::sendDeferredPacket()
if (success) {
if (!transmitList.empty() && !sendEvent->scheduled()) {
Tick time = transmitList.front().tick;
schedule(sendEvent, time <= curTick() ? curTick()+1 : time);
owner->schedule(sendEvent, time <= curTick() ? curTick()+1 : time);
}
if (transmitList.empty() && drainEvent && !sendEvent->scheduled()) {

View File

@@ -106,21 +106,14 @@ class SimpleTimingPort : public Port
Tick deferredPacketReadyTime()
{ return transmitList.empty() ? MaxTick : transmitList.front().tick; }
void
schedSendEvent(Tick when)
{
if (waitingOnRetry) {
assert(!sendEvent->scheduled());
return;
}
if (!sendEvent->scheduled()) {
schedule(sendEvent, when);
} else if (sendEvent->when() > when) {
reschedule(sendEvent, when);
}
}
/**
* Schedule a send even if not already waiting for a retry. If the
* requested time is before an already scheduled send event it
* will be rescheduled.
*
* @param when
*/
void schedSendEvent(Tick when);
/** Schedule a sendTiming() event to be called in the future.
* @param pkt packet to send