From f4be29804f96fc4abda6cde547add7285458815f Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 25 Oct 2006 18:34:21 -0400 Subject: Fix simple timing port keep a list of all packets, have only one event, and scan all packets on a functional access. --HG-- extra : convert_revision : c735a6408443b5cc90d1c1841c7aeb61e02ec6ae --- src/mem/tport.cc | 64 +++++++++++++++++++++++++++++++------------------------- src/mem/tport.hh | 33 +++++++++++++---------------- 2 files changed, 50 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/mem/tport.cc b/src/mem/tport.cc index 55a461a8b..b9d5cbe4a 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -33,15 +33,16 @@ void SimpleTimingPort::recvFunctional(PacketPtr pkt) { - std::list::iterator i = transmitList.begin(); - std::list::iterator end = transmitList.end(); + std::list >::iterator i = transmitList.begin(); + std::list >::iterator end = transmitList.end(); + bool done = false; - while (i != end) { - PacketPtr target = *i; + while (i != end && !done) { + PacketPtr target = i->second; // If the target contains data, and it overlaps the // probed request, need to update data if (target->intersect(pkt)) - fixPacket(pkt, target); + done = fixPacket(pkt, target); } @@ -63,7 +64,7 @@ SimpleTimingPort::recvTiming(PacketPtr pkt) // turn packet around to go back to requester if response expected if (pkt->needsResponse()) { pkt->makeTimingResponse(); - sendTimingLater(pkt, latency); + sendTiming(pkt, latency); } else { if (pkt->cmd != Packet::UpgradeReq) @@ -78,14 +79,14 @@ SimpleTimingPort::recvTiming(PacketPtr pkt) void SimpleTimingPort::recvRetry() { - assert(outTiming > 0); assert(!transmitList.empty()); - if (sendTiming(transmitList.front())) { + if (Port::sendTiming(transmitList.front().second)) { transmitList.pop_front(); - outTiming--; DPRINTF(Bus, "No Longer waiting on retry\n"); - if (!transmitList.empty()) - sendTimingLater(transmitList.front(), 1); + if (!transmitList.empty()) { + Tick time = transmitList.front().first; + sendEvent.schedule(time <= curTick ? curTick+1 : time); + } } if (transmitList.empty() && drainEvent) { @@ -94,39 +95,44 @@ SimpleTimingPort::recvRetry() } } +void +SimpleTimingPort::sendTiming(PacketPtr pkt, Tick time) +{ + if (transmitList.empty()) { + assert(!sendEvent.scheduled()); + sendEvent.schedule(curTick+time); + } + transmitList.push_back(std::pair(time+curTick,pkt)); +} + void SimpleTimingPort::SendEvent::process() { - assert(port->outTiming > 0); - if (!port->transmitList.empty() && port->transmitList.front() != packet) { - //We are not the head of the list - port->transmitList.push_back(packet); - } else if (port->sendTiming(packet)) { - // send successful - if (port->transmitList.size()) { - port->transmitList.pop_front(); - port->outTiming--; - if (!port->transmitList.empty()) - port->sendTimingLater(port->transmitList.front(), 1); + assert(port->transmitList.size()); + assert(port->transmitList.front().first <= curTick); + if (port->Port::sendTiming(port->transmitList.front().second)) { + //send successful, remove packet + port->transmitList.pop_front(); + if (!port->transmitList.empty()) { + Tick time = port->transmitList.front().first; + schedule(time <= curTick ? curTick+1 : time); } if (port->transmitList.empty() && port->drainEvent) { port->drainEvent->process(); port->drainEvent = NULL; } - } else { - // send unsuccessful (due to flow control). Will get retry - // callback later; save for then if not already - DPRINTF(Bus, "Waiting on retry\n"); - if (!(port->transmitList.front() == packet)) - port->transmitList.push_back(packet); + return; } + // send unsuccessful (due to flow control). Will get retry + // callback later; save for then if not already + DPRINTF(Bus, "Waiting on retry\n"); } unsigned int SimpleTimingPort::drain(Event *de) { - if (outTiming == 0 && transmitList.size() == 0) + if (transmitList.size() == 0) return 0; drainEvent = de; return 1; diff --git a/src/mem/tport.hh b/src/mem/tport.hh index fbe81c443..438ec56dc 100644 --- a/src/mem/tport.hh +++ b/src/mem/tport.hh @@ -60,23 +60,22 @@ class SimpleTimingPort : public Port protected: /** A list of outgoing timing response packets that haven't been * serviced yet. */ - std::list transmitList; + std::list > 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. */ + * a delay is requested a the event is scheduled if it isn't already. + * When the event time expires it attempts to send the packet. + * If it cannot, the packet sent when recvRetry() is called. + **/ class SendEvent : public Event { SimpleTimingPort *port; - PacketPtr packet; public: - SendEvent(SimpleTimingPort *p, PacketPtr pkt, Tick t) - : Event(&mainEventQueue), port(p), packet(pkt) - { setFlags(AutoDelete); schedule(curTick + t); } + SendEvent(SimpleTimingPort *p) + : Event(&mainEventQueue), port(p) + { } virtual void process(); @@ -84,19 +83,17 @@ class SimpleTimingPort : public Port { return "Future scheduled sendTiming event"; } }; - - /** Number of timing requests that are emulating the device timing before - * attempting to end up on the bus. - */ - int outTiming; + SendEvent sendEvent; /** 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 sendTimingLater(PacketPtr pkt, Tick time) - { outTiming++; new SendEvent(this, pkt, time); } + /** Schedule a sendTiming() event to be called in the future. + * @param pkt packet to send + * @param time increment from now (in ticks) to send packet + */ + void sendTiming(PacketPtr pkt, Tick time); /** This function is notification that the device should attempt to send a * packet again. */ @@ -118,7 +115,7 @@ class SimpleTimingPort : public Port public: SimpleTimingPort(std::string pname) - : Port(pname), outTiming(0), drainEvent(NULL) + : Port(pname), sendEvent(this), drainEvent(NULL) {} /** Hook for draining timing accesses from the system. The -- cgit v1.2.3