Restructure bus timing calcs to cope with pkt being deleted by target.

--HG--
extra : convert_revision : db8497e73a44f2a06aab121e797e88b4c0c31330
This commit is contained in:
Steve Reinhardt 2008-03-17 03:07:38 -04:00
parent 19c367fa8f
commit 131c65f429
2 changed files with 29 additions and 23 deletions

View file

@ -110,21 +110,22 @@ const char * Bus::BusFreeEvent::description() const
return "bus became available";
}
void Bus::preparePacket(PacketPtr pkt, Tick & headerTime)
Tick Bus::calcPacketTiming(PacketPtr pkt)
{
//Bring tickNextIdle up to the present tick
//There is some potential ambiguity where a cycle starts, which might make
//a difference when devices are acting right around a cycle boundary. Using
//a < allows things which happen exactly on a cycle boundary to take up
//only the following cycle. Anything that happens later will have to "wait"
//for the end of that cycle, and then start using the bus after that.
// Bring tickNextIdle up to the present tick.
// There is some potential ambiguity where a cycle starts, which
// might make a difference when devices are acting right around a
// cycle boundary. Using a < allows things which happen exactly on
// a cycle boundary to take up only the following cycle. Anything
// that happens later will have to "wait" for the end of that
// cycle, and then start using the bus after that.
if (tickNextIdle < curTick) {
tickNextIdle = curTick;
if (tickNextIdle % clock != 0)
tickNextIdle = curTick - (curTick % clock) + clock;
}
headerTime = tickNextIdle + headerCycles * clock;
Tick headerTime = tickNextIdle + headerCycles * clock;
// The packet will be sent. Figure out how long it occupies the bus, and
// how much of that time is for the first "word", aka bus width.
@ -142,10 +143,17 @@ void Bus::preparePacket(PacketPtr pkt, Tick & headerTime)
pkt->firstWordTime = headerTime + clock;
pkt->finishTime = headerTime + numCycles * clock;
return headerTime;
}
void Bus::occupyBus(Tick until)
{
if (until == 0) {
// shortcut for express snoop packets
return;
}
tickNextIdle = until;
if (!busIdle.scheduled()) {
@ -190,11 +198,8 @@ Bus::recvTiming(PacketPtr pkt)
DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x\n",
src, pkt->getDest(), pkt->cmdString(), pkt->getAddr());
Tick headerTime = 0;
if (!pkt->isExpressSnoop()) {
preparePacket(pkt, headerTime);
}
Tick headerFinishTime = pkt->isExpressSnoop() ? 0 : calcPacketTiming(pkt);
Tick packetFinishTime = pkt->isExpressSnoop() ? 0 : pkt->finishTime;
short dest = pkt->getDest();
int dest_port_id;
@ -243,17 +248,16 @@ Bus::recvTiming(PacketPtr pkt)
DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x TGT RETRY\n",
src, pkt->getDest(), pkt->cmdString(), pkt->getAddr());
addToRetryList(src_port);
if (!pkt->isExpressSnoop()) {
occupyBus(headerTime);
}
occupyBus(headerFinishTime);
return false;
}
// send OK, fall through
// send OK, fall through... pkt may have been deleted by
// target at this point, so it should *not* be referenced
// again. We'll set it to NULL here just to be safe.
pkt = NULL;
}
if (!pkt->isExpressSnoop()) {
occupyBus(pkt->finishTime);
}
occupyBus(packetFinishTime);
// Packet was successfully sent.
// Also take care of retries

View file

@ -245,10 +245,12 @@ class Bus : public MemObject
*/
void addressRanges(AddrRangeList &resp, bool &snoop, int id);
/** Prepare a packet to be sent on the bus. The header finishes at tick
* headerTime
/** Calculate the timing parameters for the packet. Updates the
* firstWordTime and finishTime fields of the packet object.
* Returns the tick at which the packet header is completed (which
* will be all that is sent if the target rejects the packet).
*/
void preparePacket(PacketPtr pkt, Tick & headerTime);
Tick calcPacketTiming(PacketPtr pkt);
/** Occupy the bus until until */
void occupyBus(Tick until);