diff -r df4148b7d60a -r ddeec93f45f8 src/mem/bus.hh --- a/src/mem/bus.hh Thu Feb 14 09:57:29 2013 +0000 +++ b/src/mem/bus.hh Thu Feb 14 09:57:43 2013 +0000 @@ -302,12 +302,13 @@ */ AddrRangeList getAddrRanges() const; - /** 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). + /** + * Calculate the timing parameters for the packet. Updates the + * busFirstWordDelay and busLastWordDelay fields of the packet + * object with the relative number of ticks required to transmit + * the header and the first word, and the last word, respectively. */ - Tick calcPacketTiming(PacketPtr pkt); + void calcPacketTiming(PacketPtr pkt); /** * Ask everyone on the bus what their size is and determine the diff -r df4148b7d60a -r ddeec93f45f8 src/mem/bus.cc --- a/src/mem/bus.cc Thu Feb 14 09:57:29 2013 +0000 +++ b/src/mem/bus.cc Thu Feb 14 09:57:43 2013 +0000 @@ -129,32 +129,24 @@ } } -Tick +void BaseBus::calcPacketTiming(PacketPtr pkt) { - // determine the header time rounded to the closest following - // clock edge - Tick headerTime = clockEdge(Cycles(headerCycles)); + // the bus will be called at a time that is not necessarily + // coinciding with its own clock, so start by determining how long + // until the next clock edge (could be zero) + Tick offset = nextCycle() - curTick(); - // 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. - Cycles numCycles(0); - if (pkt->hasData()) { - // If a packet has data, it needs ceil(size/width) cycles to send it - unsigned dataSize = pkt->getSize(); - numCycles = Cycles(dataSize / width); - if (dataSize % width) - ++numCycles; - } + // determine how many cycles are needed to send the data + unsigned dataCycles = pkt->hasData() ? divCeil(pkt->getSize(), width) : 0; // The first word will be delivered on the cycle after the header. - pkt->firstWordTime = headerTime + clockPeriod(); + pkt->busFirstWordDelay = (headerCycles + 1) * clockPeriod() + offset; - // Note that currently finishTime can be smaller than - // firstWordTime if the packet has no data - pkt->finishTime = headerTime + numCycles * clockPeriod(); - - return headerTime; + // Note that currently lastWordDelay can be smaller than + // firstWordDelay if the packet has no data + pkt->busLastWordDelay = (headerCycles + dataCycles) * clockPeriod() + + offset; } template diff -r df4148b7d60a -r ddeec93f45f8 src/mem/cache/cache_impl.hh --- a/src/mem/cache/cache_impl.hh Thu Feb 14 09:57:29 2013 +0000 +++ b/src/mem/cache/cache_impl.hh Thu Feb 14 09:57:43 2013 +0000 @@ -887,8 +887,9 @@ // responseLatency is the latency of the return path // from lower level caches/memory to an upper level cache or // the core. - completion_time = responseLatency * clockPeriod() + - (transfer_offset ? pkt->finishTime : pkt->firstWordTime); + completion_time = curTick() + responseLatency * clockPeriod() + + (transfer_offset ? pkt->busLastWordDelay : + pkt->busFirstWordDelay); assert(!target->pkt->req->isUncacheable()); @@ -903,15 +904,15 @@ // responseLatency is the latency of the return path // from lower level caches/memory to an upper level cache or // the core. - completion_time = responseLatency * clockPeriod() + - pkt->finishTime; + completion_time = curTick() + responseLatency * clockPeriod() + + pkt->busLastWordDelay; target->pkt->req->setExtraData(0); } else { // not a cache fill, just forwarding response // responseLatency is the latency of the return path // from lower level cahces/memory to the core. - completion_time = responseLatency * clockPeriod() + - pkt->finishTime; + completion_time = curTick() + responseLatency * clockPeriod() + + pkt->busLastWordDelay; if (pkt->isRead() && !is_error) { target->pkt->setData(pkt->getPtr()); } @@ -973,7 +974,8 @@ } MSHRQueue *mq = mshr->queue; mq->markPending(mshr); - requestMemSideBus((RequestCause)mq->index, pkt->finishTime); + requestMemSideBus((RequestCause)mq->index, curTick() + + pkt->busLastWordDelay); } else { mq->deallocate(mshr); if (wasFull && !mq->isFull()) { @@ -1206,7 +1208,7 @@ std::memcpy(blk->data, pkt->getPtr(), blkSize); } - blk->whenReady = pkt->finishTime; + blk->whenReady = curTick() + pkt->busLastWordDelay; return blk; } @@ -1558,7 +1560,7 @@ pkt = new Packet(tgt_pkt); pkt->cmd = MemCmd::UpgradeFailResp; pkt->senderState = mshr; - pkt->firstWordTime = pkt->finishTime = curTick(); + pkt->busFirstWordDelay = pkt->busLastWordDelay = 0; handleResponse(pkt); return NULL; } else if (mshr->isForwardNoResponse()) { diff -r df4148b7d60a -r ddeec93f45f8 src/mem/coherent_bus.cc --- a/src/mem/coherent_bus.cc Thu Feb 14 09:57:29 2013 +0000 +++ b/src/mem/coherent_bus.cc Thu Feb 14 09:57:43 2013 +0000 @@ -133,8 +133,8 @@ // set the source port for routing of the response pkt->setSrc(slave_port_id); - Tick headerFinishTime = is_express_snoop ? 0 : calcPacketTiming(pkt); - Tick packetFinishTime = is_express_snoop ? 0 : pkt->finishTime; + calcPacketTiming(pkt); + Tick packetFinishTime = pkt->busLastWordDelay + curTick(); // uncacheable requests need never be snooped if (!pkt->req->isUncacheable()) { @@ -181,7 +181,7 @@ src_port->name(), pkt->cmdString(), pkt->getAddr()); // update the bus state and schedule an idle event - reqLayer.failedTiming(src_port, headerFinishTime); + reqLayer.failedTiming(src_port, clockEdge(Cycles(headerCycles))); } else { // update the bus state and schedule an idle event reqLayer.succeededTiming(packetFinishTime); @@ -209,7 +209,7 @@ src_port->name(), pkt->cmdString(), pkt->getAddr()); calcPacketTiming(pkt); - Tick packetFinishTime = pkt->finishTime; + Tick packetFinishTime = pkt->busLastWordDelay + curTick(); // the packet is a normal response to a request that we should // have seen passing through the bus @@ -279,7 +279,7 @@ assert(!pkt->isExpressSnoop()); calcPacketTiming(pkt); - Tick packetFinishTime = pkt->finishTime; + Tick packetFinishTime = pkt->busLastWordDelay + curTick(); // determine if the response is from a snoop request we // created as the result of a normal request (in which case it @@ -380,7 +380,8 @@ response_latency = snoop_response_latency; } - pkt->finishTime = curTick() + response_latency; + // @todo: Not setting first-word time + pkt->busLastWordDelay = response_latency; return response_latency; } @@ -400,7 +401,8 @@ if (snoop_response_cmd != MemCmd::InvalidCmd) pkt->cmd = snoop_response_cmd; - pkt->finishTime = curTick() + snoop_response_latency; + // @todo: Not setting first-word time + pkt->busLastWordDelay = snoop_response_latency; return snoop_response_latency; } diff -r df4148b7d60a -r ddeec93f45f8 src/mem/noncoherent_bus.cc --- a/src/mem/noncoherent_bus.cc Thu Feb 14 09:57:29 2013 +0000 +++ b/src/mem/noncoherent_bus.cc Thu Feb 14 09:57:43 2013 +0000 @@ -110,8 +110,8 @@ // set the source port for routing of the response pkt->setSrc(slave_port_id); - Tick headerFinishTime = calcPacketTiming(pkt); - Tick packetFinishTime = pkt->finishTime; + calcPacketTiming(pkt); + Tick packetFinishTime = pkt->busLastWordDelay + curTick(); // since it is a normal request, determine the destination // based on the address and attempt to send the packet @@ -124,7 +124,8 @@ DPRINTF(NoncoherentBus, "recvTimingReq: src %s %s 0x%x RETRY\n", src_port->name(), pkt->cmdString(), pkt->getAddr()); - reqLayer.failedTiming(src_port, headerFinishTime); + // occupy until the header is sent + reqLayer.failedTiming(src_port, clockEdge(Cycles(headerCycles))); return false; } @@ -152,7 +153,7 @@ src_port->name(), pkt->cmdString(), pkt->getAddr()); calcPacketTiming(pkt); - Tick packetFinishTime = pkt->finishTime; + Tick packetFinishTime = pkt->busLastWordDelay + curTick(); // send the packet to the destination through one of our slave // ports, as determined by the destination field @@ -189,7 +190,8 @@ // forward the request to the appropriate destination Tick response_latency = masterPorts[dest_id]->sendAtomic(pkt); - pkt->finishTime = curTick() + response_latency; + // @todo: Not setting first-word time + pkt->busLastWordDelay = response_latency; return response_latency; } diff -r df4148b7d60a -r ddeec93f45f8 src/mem/packet.hh --- a/src/mem/packet.hh Thu Feb 14 09:57:29 2013 +0000 +++ b/src/mem/packet.hh Thu Feb 14 09:57:43 2013 +0000 @@ -330,11 +330,23 @@ public: - /// The time at which the packet will be fully transmitted - Tick finishTime; + /** + * The extra delay from seeing the packet until the first word is + * transmitted by the bus that provided it (if any). This delay is + * used to communicate the bus waiting time to the neighbouring + * object (e.g. a cache) that actually makes the packet wait. As + * the delay is relative, a 32-bit unsigned should be sufficient. + */ + uint32_t busFirstWordDelay; - /// The time at which the first chunk of the packet will be transmitted - Tick firstWordTime; + /** + * The extra delay from seeing the packet until the last word is + * transmitted by the bus that provided it (if any). Similar to + * the first word time, this is used to make up for the fact that + * the bus does not make the packet wait. As the delay is relative, + * a 32-bit unsigned should be sufficient. + */ + uint32_t busLastWordDelay; /** * A virtual base opaque structure used to hold state associated @@ -545,6 +557,7 @@ : cmd(_cmd), req(_req), data(NULL), src(InvalidPortID), dest(InvalidPortID), bytesValidStart(0), bytesValidEnd(0), + busFirstWordDelay(0), busLastWordDelay(0), senderState(NULL) { if (req->hasPaddr()) { @@ -566,6 +579,7 @@ : cmd(_cmd), req(_req), data(NULL), src(InvalidPortID), dest(InvalidPortID), bytesValidStart(0), bytesValidEnd(0), + busFirstWordDelay(0), busLastWordDelay(0), senderState(NULL) { if (req->hasPaddr()) { @@ -587,7 +601,10 @@ : cmd(pkt->cmd), req(pkt->req), data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL), addr(pkt->addr), size(pkt->size), src(pkt->src), dest(pkt->dest), - bytesValidStart(pkt->bytesValidStart), bytesValidEnd(pkt->bytesValidEnd), + bytesValidStart(pkt->bytesValidStart), + bytesValidEnd(pkt->bytesValidEnd), + busFirstWordDelay(pkt->busFirstWordDelay), + busLastWordDelay(pkt->busLastWordDelay), senderState(pkt->senderState) { if (!clearFlags) @@ -626,6 +643,13 @@ addr = req->getPaddr(); size = req->getSize(); + src = InvalidPortID; + dest = InvalidPortID; + bytesValidStart = 0; + bytesValidEnd = 0; + busFirstWordDelay = 0; + busLastWordDelay = 0; + flags.set(VALID_ADDR|VALID_SIZE); deleteData(); }