44d43
< #include "debug/Bus.hh"
48,53c47,49
< using namespace std;
<
< SimpleTimingPort::SimpleTimingPort(const string &_name, MemObject *_owner,
< const string _label)
< : Port(_name, _owner), label(_label), sendEvent(this), drainEvent(NULL),
< waitingOnRetry(false)
---
> SimpleTimingPort::SimpleTimingPort(const std::string& _name,
> MemObject* _owner) :
> QueuedPort(_name, _owner, queue), queue(*_owner, *this)
57,81d52
< SimpleTimingPort::~SimpleTimingPort()
< {
< }
<
< bool
< SimpleTimingPort::checkFunctional(PacketPtr pkt)
< {
< pkt->pushLabel(label);
<
< DeferredPacketIterator i = transmitList.begin();
< DeferredPacketIterator end = transmitList.end();
< bool found = false;
<
< while (!found && i != end) {
< // If the buffered packet contains data, and it overlaps the
< // current packet, then update data
< found = pkt->checkFunctional(i->pkt);
< ++i;
< }
<
< pkt->popLabel();
<
< return found;
< }
<
85,86c56,58
< if (!checkFunctional(pkt)) {
< // Just do an atomic access and throw away the returned latency
---
> assert(pkt->isRequest());
> if (!queue.checkFunctional(pkt)) {
> // do an atomic access and throw away the returned latency
94,99d65
< // If the device is only a slave, it should only be sending
< // responses, which should never get nacked. There used to be
< // code to hanldle nacks here, but I'm pretty sure it didn't work
< // correctly with the drain code, so that would need to be fixed
< // if we ever added it back.
<
114c80
< schedSendTiming(pkt, curTick() + latency);
---
> queue.schedSendTiming(pkt, curTick() + latency);
121,252d86
<
< void
< SimpleTimingPort::schedSendEvent(Tick when)
< {
< // if we are waiting on a retry, do not schedule a send event, and
< // instead rely on retry being called
< 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)
< {
< assert(when > curTick());
< assert(when < curTick() + SimClock::Int::ms);
<
< // Nothing is on the list: add it and schedule an event
< if (transmitList.empty() || when < transmitList.front().tick) {
< transmitList.push_front(DeferredPacket(when, pkt));
< schedSendEvent(when);
< return;
< }
<
< // list is non-empty & this belongs at the end
< if (when >= transmitList.back().tick) {
< transmitList.push_back(DeferredPacket(when, pkt));
< return;
< }
<
< // this belongs in the middle somewhere
< DeferredPacketIterator i = transmitList.begin();
< i++; // already checked for insertion at front
< DeferredPacketIterator end = transmitList.end();
<
< for (; i != end; ++i) {
< if (when < i->tick) {
< transmitList.insert(i, DeferredPacket(when, pkt));
< return;
< }
< }
< assert(false); // should never get here
< }
<
< void SimpleTimingPort::trySendTiming()
< {
< assert(deferredPacketReady());
< // take the next packet off the list here, as we might return to
< // ourselves through the sendTiming call below
< DeferredPacket dp = transmitList.front();
< transmitList.pop_front();
<
< // attempt to send the packet and remember the outcome
< waitingOnRetry = !sendTiming(dp.pkt);
<
< if (waitingOnRetry) {
< // put the packet back at the front of the list (packet should
< // not have changed since it wasn't accepted)
< assert(!sendEvent.scheduled());
< transmitList.push_front(dp);
< }
< }
<
< void
< SimpleTimingPort::scheduleSend(Tick time)
< {
< // the next ready time is either determined by the next deferred packet,
< // or in the cache through the MSHR ready time
< Tick nextReady = std::min(deferredPacketReadyTime(), time);
< if (nextReady != MaxTick) {
< // if the sendTiming caused someone else to call our
< // recvTiming we could already have an event scheduled, check
< if (!sendEvent.scheduled())
< owner->schedule(&sendEvent, std::max(nextReady, curTick() + 1));
< } else {
< // no more to send, so if we're draining, we may be done
< if (drainEvent && !sendEvent.scheduled()) {
< drainEvent->process();
< drainEvent = NULL;
< }
< }
< }
<
< void
< SimpleTimingPort::sendDeferredPacket()
< {
< // try to send what is on the list
< trySendTiming();
<
< // if we succeeded and are not waiting for a retry, schedule the
< // next send
< if (!waitingOnRetry) {
< scheduleSend();
< }
< }
<
<
< void
< SimpleTimingPort::recvRetry()
< {
< DPRINTF(Bus, "Received retry\n");
< // note that in the cache we get a retry even though we may not
< // have a packet to retry (we could potentially decide on a new
< // packet every time we retry)
< assert(waitingOnRetry);
< sendDeferredPacket();
< }
<
<
< void
< SimpleTimingPort::processSendEvent()
< {
< assert(!waitingOnRetry);
< sendDeferredPacket();
< }
<
<
< unsigned int
< SimpleTimingPort::drain(Event *de)
< {
< if (transmitList.empty() && !sendEvent.scheduled())
< return 0;
< drainEvent = de;
< return 1;
< }