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:
parent
5448517da4
commit
ab44417282
3 changed files with 45 additions and 32 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue