diff options
-rw-r--r-- | src/mem/bus.cc | 68 | ||||
-rw-r--r-- | src/mem/bus.hh | 2 | ||||
-rw-r--r-- | src/mem/packet.hh | 7 | ||||
-rw-r--r-- | src/mem/tport.cc | 9 |
4 files changed, 52 insertions, 34 deletions
diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 7584ffffd..66cd581e7 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -82,33 +82,6 @@ const char * Bus::BusFreeEvent::description() return "bus became available"; } -void -Bus::occupyBus(int numCycles) -{ - //Move up when the bus will next be free - //We avoid the use of divide by adding repeatedly - //This should be faster if the value is updated frequently, but should - //be may be slower otherwise. - - //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. Anthing that happens later will have to "wait" for the - //end of that cycle, and then start using the bus after that. - while (tickNextIdle < curTick) - tickNextIdle += clock; - //Advance it numCycles bus cycles. - //XXX Should this use the repeating add trick as well? - tickNextIdle += (numCycles * clock); - if (!busIdle.scheduled()) { - busIdle.schedule(tickNextIdle); - } else { - busIdle.reschedule(tickNextIdle); - } - DPRINTF(Bus, "The bus is now occupied from tick %d to %d\n", curTick, tickNextIdle); -} - /** Function called by the port when the bus is receiving a Timing * transaction.*/ bool @@ -120,6 +93,14 @@ Bus::recvTiming(Packet *pkt) Port *pktPort = interfaces[pkt->getSrc()]; + // If the bus is busy, or other devices are in line ahead of the current + // one, put this device on the retry list. + if (tickNextIdle > curTick || + (retryList.size() && pktPort != retryingPort)) { + addToRetryList(pktPort); + return false; + } + short dest = pkt->getDest(); if (dest == Packet::Broadcast) { if (timingSnoop(pkt)) { @@ -146,7 +127,17 @@ Bus::recvTiming(Packet *pkt) port = interfaces[dest]; } - // The packet will be sent. Figure out how long it occupies the bus. + //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. Anthing that happens later will have to "wait" for + //the end of that cycle, and then start using the bus after that. + while (tickNextIdle < curTick) + tickNextIdle += 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. int numCycles = 0; // Requests need one cycle to send an address if (pkt->isRequest()) @@ -167,7 +158,26 @@ Bus::recvTiming(Packet *pkt) } } - occupyBus(numCycles); + // The first word will be delivered after the current tick, the delivery + // of the address if any, and one bus cycle to deliver the data + pkt->firstWordTime = + tickNextIdle + + pkt->isRequest() ? clock : 0 + + clock; + + //Advance it numCycles bus cycles. + //XXX Should this use the repeated addition trick as well? + tickNextIdle += (numCycles * clock); + if (!busIdle.scheduled()) { + busIdle.schedule(tickNextIdle); + } else { + busIdle.reschedule(tickNextIdle); + } + DPRINTF(Bus, "The bus is now occupied from tick %d to %d\n", + curTick, tickNextIdle); + + // The bus will become idle once the current packet is delivered. + pkt->finishTime = tickNextIdle; if (port->sendTiming(pkt)) { // Packet was successfully sent. Return true. diff --git a/src/mem/bus.hh b/src/mem/bus.hh index a89738775..ce3f4bed7 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -195,8 +195,6 @@ class Bus : public MemObject BusFreeEvent busIdle; - void occupyBus(int numCycles); - Port * retryingPort; /** An array of pointers to the peer port interfaces diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 7ec061710..3a7286a69 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -92,7 +92,6 @@ class Packet * be called on it rather than simply delete.*/ bool arrayData; - /** The address of the request. This address could be virtual or * physical, depending on the system configuration. */ Addr addr; @@ -124,6 +123,12 @@ class Packet /** Used to calculate latencies for each packet.*/ Tick time; + /** The time at which the packet will be fully transmitted */ + Tick finishTime; + + /** The time at which the first chunk of the packet will be transmitted */ + Tick firstWordTime; + /** The special destination address indicating that the packet * should be routed based on its address. */ static const short Broadcast = -1; diff --git a/src/mem/tport.cc b/src/mem/tport.cc index cef7a2a5b..66811b820 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -59,6 +59,8 @@ void SimpleTimingPort::recvRetry() { bool result = true; + + assert(transmitList.size()); while (result && transmitList.size()) { result = sendTiming(transmitList.front()); if (result) @@ -75,8 +77,11 @@ SimpleTimingPort::SendEvent::process() { port->outTiming--; assert(port->outTiming >= 0); - if (port->sendTiming(packet)) { - // send successfule + if (port->transmitList.size()) { + port->transmitList.push_back(packet); + } + else if (port->sendTiming(packet)) { + // send successful if (port->transmitList.size() == 0 && port->drainEvent) { port->drainEvent->process(); port->drainEvent = NULL; |