summaryrefslogtreecommitdiff
path: root/src/mem/bus.hh
diff options
context:
space:
mode:
authorAndreas Hansson <andreas.hansson@arm.com>2012-07-09 12:35:35 -0400
committerAndreas Hansson <andreas.hansson@arm.com>2012-07-09 12:35:35 -0400
commit14f9c77dd36fef8ab509bc17ecbe422555daa9c6 (patch)
treeab41774b5efb34fd0b72f06b5f1011cca9260538 /src/mem/bus.hh
parent46d9adb68c96b94ae25bbe92d34e375daf532ece (diff)
downloadgem5-14f9c77dd36fef8ab509bc17ecbe422555daa9c6.tar.xz
Bus: Replace tickNextIdle and inRetry with a state variable
This patch adds a state enum and member variable in the bus, tracking the bus state, thus eliminating the need for tickNextIdle and inRetry, and fixing an issue that allowed the bus to be occupied by multiple packets at once (hopefully it also makes it easier to understand the code). The bus, in its current form, uses tickNextIdle and inRetry to keep track of the state of the bus. However, it only updates tickNextIdle _after_ forwarding a packet using sendTiming, and the result is that the bus is still seen as idle, and a module that receives the packet and starts transmitting new packets in zero time will still see the bus as idle (and this is done by a number of DMA devices). The issue can also be seen in isOccupied where the bus calls reschedule on an event instead of schedule. This patch addresses the problem by marking the bus as _not_ idle already by the time we conclude that the bus is not occupied and we will deal with the packet. As a result of not allowing multiple packets to occupy the bus, some regressions have slight changes in their statistics. A separate patch updates these accordingly. Further ahead, a follow-on patch will introduce a separate state variable for request/responses/snoop responses, and thus implement a split request/response bus with separate flow control for the different message types (even further ahead it will introduce a multi-layer bus).
Diffstat (limited to 'src/mem/bus.hh')
-rw-r--r--src/mem/bus.hh63
1 files changed, 34 insertions, 29 deletions
diff --git a/src/mem/bus.hh b/src/mem/bus.hh
index 94068d897..db0686683 100644
--- a/src/mem/bus.hh
+++ b/src/mem/bus.hh
@@ -74,14 +74,32 @@ class BaseBus : public MemObject
protected:
+ /**
+ * We declare an enum to track the state of the bus. The starting
+ * point is an idle state where the bus is waiting for a packet to
+ * arrive. Upon arrival, the bus transitions to the busy state,
+ * where it remains either until the packet transfer is done, or
+ * the header time is spent. Once the bus leaves the busy state,
+ * it can either go back to idle, if no packets have arrived while
+ * it was busy, or the bus goes on to retry the first port on the
+ * retryList. A similar transition takes place from idle to retry
+ * if the bus receives a retry from one of its connected
+ * ports. The retry state lasts until the port in questions calls
+ * sendTiming and returns control to the bus, or goes to a busy
+ * state if the port does not immediately react to the retry by
+ * calling sendTiming.
+ */
+ enum State { IDLE, BUSY, RETRY };
+
+ /** track the state of the bus */
+ State state;
+
/** the clock speed for the bus */
int clock;
/** cycles of overhead per transaction */
int headerCycles;
/** the width of the bus in bytes */
int width;
- /** the next tick at which the bus will be idle */
- Tick tickNextIdle;
Event * drainEvent;
@@ -92,15 +110,15 @@ class BaseBus : public MemObject
AddrRangeList defaultRange;
/**
- * Determine if the bus is to be considered occupied when being
- * presented with a packet from a specific port. If so, the port
- * in question is also added to the retry list.
+ * Determine if the bus accepts a packet from a specific port. If
+ * not, the port in question is also added to the retry list. In
+ * either case the state of the bus is updated accordingly.
*
* @param port Source port on the bus presenting the packet
*
- * @return True if the bus is to be considered occupied
+ * @return True if the bus accepts the packet
*/
- bool isOccupied(Port* port);
+ bool tryTiming(Port* port);
/**
* Deal with a destination port accepting a packet by potentially
@@ -111,6 +129,15 @@ class BaseBus : public MemObject
*/
void succeededTiming(Tick busy_time);
+ /**
+ * Deal with a destination port not accepting a packet by
+ * potentially adding the source port to the retry list (if
+ * not already at the front) and occupying the bus accordingly.
+ *
+ * @param busy_time Time to spend as a result of a failed send
+ */
+ void failedTiming(SlavePort* port, Tick busy_time);
+
/** Timing function called by port when it is once again able to process
* requests. */
void recvRetry();
@@ -223,7 +250,6 @@ class BaseBus : public MemObject
// event used to schedule a release of the bus
EventWrapper<BaseBus, &BaseBus::releaseBus> busIdleEvent;
- bool inRetry;
std::set<PortID> inRecvRangeChange;
/** The master and slave ports of the bus */
@@ -240,25 +266,6 @@ class BaseBus : public MemObject
* original send failed for whatever reason.*/
std::list<Port*> retryList;
- void addToRetryList(Port* port)
- {
- if (!inRetry) {
- // The device wasn't retrying a packet, or wasn't at an
- // appropriate time.
- retryList.push_back(port);
- } else {
- if (!retryList.empty() && port == retryList.front()) {
- // The device was retrying a packet. It didn't work,
- // so we'll leave it at the head of the retry list.
- inRetry = false;
- } else {
- // We are in retry, but not for this port, put it at
- // the end.
- retryList.push_back(port);
- }
- }
- }
-
/** Port that handles requests that don't match any of the interfaces.*/
PortID defaultPortID;
@@ -282,8 +289,6 @@ class BaseBus : public MemObject
virtual MasterPort& getMasterPort(const std::string& if_name, int idx = -1);
virtual SlavePort& getSlavePort(const std::string& if_name, int idx = -1);
- virtual void startup();
-
unsigned int drain(Event *de);
};