From ab444172828e26dfdd35f4a9fcc9c73b9693f7fe Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Mon, 9 Oct 2006 23:24:21 -0400 Subject: [PATCH] Fixes to the bus, and added fields to the packet. src/mem/bus.cc: Put back the check to see if the bus is busy. Also, populate the fields in the packet to indicate when the first word and the entire packet will be delivered. src/mem/bus.hh: Remove the occupyBus function. src/mem/packet.hh: Added fields to the packet to indicate when the first chunk of a packet arrives, and when the entire packet arrives. --HG-- extra : convert_revision : cfc7670a33913d48a04d02c6d2448290a51f2d3c --- src/mem/bus.cc | 68 +++++++++++++++++++++++++++-------------------- src/mem/bus.hh | 2 -- src/mem/packet.hh | 7 ++++- 3 files changed, 45 insertions(+), 32 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 4d57aee75..28864522f 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -90,7 +90,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; @@ -122,6 +121,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;