summaryrefslogtreecommitdiff
path: root/src/mem/bus.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/bus.cc')
-rw-r--r--src/mem/bus.cc68
1 files changed, 39 insertions, 29 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.