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
This commit is contained in:
Gabe Black 2006-10-09 23:24:21 -04:00
parent 5448517da4
commit ab44417282
3 changed files with 45 additions and 32 deletions

View file

@ -82,33 +82,6 @@ const char * Bus::BusFreeEvent::description()
return "bus became available"; 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 /** Function called by the port when the bus is receiving a Timing
* transaction.*/ * transaction.*/
bool bool
@ -120,6 +93,14 @@ Bus::recvTiming(Packet *pkt)
Port *pktPort = interfaces[pkt->getSrc()]; 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(); short dest = pkt->getDest();
if (dest == Packet::Broadcast) { if (dest == Packet::Broadcast) {
if (timingSnoop(pkt)) { if (timingSnoop(pkt)) {
@ -146,7 +127,17 @@ Bus::recvTiming(Packet *pkt)
port = interfaces[dest]; 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; int numCycles = 0;
// Requests need one cycle to send an address // Requests need one cycle to send an address
if (pkt->isRequest()) 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)) { if (port->sendTiming(pkt)) {
// Packet was successfully sent. Return true. // Packet was successfully sent. Return true.

View file

@ -195,8 +195,6 @@ class Bus : public MemObject
BusFreeEvent busIdle; BusFreeEvent busIdle;
void occupyBus(int numCycles);
Port * retryingPort; Port * retryingPort;
/** An array of pointers to the peer port interfaces /** An array of pointers to the peer port interfaces

View file

@ -90,7 +90,6 @@ class Packet
* be called on it rather than simply delete.*/ * be called on it rather than simply delete.*/
bool arrayData; bool arrayData;
/** The address of the request. This address could be virtual or /** The address of the request. This address could be virtual or
* physical, depending on the system configuration. */ * physical, depending on the system configuration. */
Addr addr; Addr addr;
@ -122,6 +121,12 @@ class Packet
/** Used to calculate latencies for each packet.*/ /** Used to calculate latencies for each packet.*/
Tick time; 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 /** The special destination address indicating that the packet
* should be routed based on its address. */ * should be routed based on its address. */
static const short Broadcast = -1; static const short Broadcast = -1;