#include "mem/tport.hh"
void
-SimpleTimingPort::recvFunctional(Packet *pkt)
+SimpleTimingPort::recvFunctional(PacketPtr pkt)
{
- // just do an atomic access and throw away the returned latency
- recvAtomic(pkt);
+ std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin();
+ std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end();
+ bool notDone = true;
+
+ while (i != end && notDone) {
+ PacketPtr target = i->second;
+ // If the target contains data, and it overlaps the
+ // probed request, need to update data
+ if (target->intersect(pkt))
+ notDone = fixPacket(pkt, target);
+
+ i++;
+ }
+
+ //Then just do an atomic access and throw away the returned latency
+ if (pkt->result != Packet::Success)
+ recvAtomic(pkt);
}
bool
-SimpleTimingPort::recvTiming(Packet *pkt)
+SimpleTimingPort::recvTiming(PacketPtr pkt)
{
// If the device is only a slave, it should only be sending
// responses, which should never get nacked. There used to be
// 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 != MemCmd::UpgradeReq)
+ {
+ delete pkt->req;
+ delete pkt;
+ }
}
return true;
}
void
SimpleTimingPort::recvRetry()
{
- bool result = true;
-
- assert(transmitList.size());
- while (result && transmitList.size()) {
- result = sendTiming(transmitList.front());
- if (result)
- transmitList.pop_front();
+ assert(!transmitList.empty());
+ if (Port::sendTiming(transmitList.front().second)) {
+ transmitList.pop_front();
+ DPRINTF(Bus, "No Longer waiting on retry\n");
+ if (!transmitList.empty()) {
+ Tick time = transmitList.front().first;
+ sendEvent.schedule(time <= curTick ? curTick+1 : time);
+ }
}
- if (transmitList.size() == 0 && drainEvent) {
+
+ if (transmitList.empty() && drainEvent) {
drainEvent->process();
drainEvent = NULL;
}
}
void
-SimpleTimingPort::SendEvent::process()
+SimpleTimingPort::sendTiming(PacketPtr pkt, Tick time)
{
- port->outTiming--;
- assert(port->outTiming >= 0);
- if (port->transmitList.size()) {
- port->transmitList.push_back(packet);
+ // Nothing is on the list: add it and schedule an event
+ if (transmitList.empty()) {
+ assert(!sendEvent.scheduled());
+ sendEvent.schedule(curTick+time);
+ transmitList.push_back(std::pair<Tick,PacketPtr>(time+curTick,pkt));
+ return;
}
- else if (port->sendTiming(packet)) {
- // send successful
- if (port->transmitList.size() == 0 && port->drainEvent) {
+
+ // something is on the list and this belongs at the end
+ if (time+curTick >= transmitList.back().first) {
+ transmitList.push_back(std::pair<Tick,PacketPtr>(time+curTick,pkt));
+ return;
+ }
+ // Something is on the list and this belongs somewhere else
+ std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin();
+ std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end();
+ bool done = false;
+
+ while (i != end && !done) {
+ if (time+curTick < i->first) {
+ if (i == transmitList.begin()) {
+ //Inserting at begining, reschedule
+ sendEvent.reschedule(time+curTick);
+ }
+ transmitList.insert(i,std::pair<Tick,PacketPtr>(time+curTick,pkt));
+ done = true;
+ }
+ i++;
+ }
+}
+
+void
+SimpleTimingPort::SendEvent::process()
+{
+ 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.
- 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;