/*
- * Copyright (c) 2011-2012 ARM Limited
+ * Copyright (c) 2011-2013 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
#ifndef __MEM_BUS_HH__
#define __MEM_BUS_HH__
-#include <list>
+#include <deque>
#include <set>
#include "base/addr_range_map.hh"
* whereas a response layer holds master ports.
*/
template <typename PortClass>
- class Layer
+ class Layer : public Drainable
{
public:
*
* @param _bus the bus this layer belongs to
* @param _name the layer's name
- * @param _clock clock period in ticks
*/
- Layer(BaseBus& _bus, const std::string& _name, Tick _clock);
+ Layer(BaseBus& _bus, const std::string& _name);
/**
* Drain according to the normal semantics, so that the bus
*
* @return 1 if busy or waiting to retry, or 0 if idle
*/
- unsigned int drain(Event *de);
+ unsigned int drain(DrainManager *dm);
/**
* Get the bus layer's name
/** track the state of the bus layer */
State state;
- /** the clock speed for the bus layer */
- Tick clock;
-
- /** event for signalling when drained */
- Event * drainEvent;
+ /** manager to signal when drained */
+ DrainManager *drainManager;
/**
* An array of ports that retry should be called
* on because the original send failed for whatever reason.
*/
- std::list<PortClass*> retryList;
+ std::deque<PortClass*> retryList;
+
+ /**
+ * Port that we are currently in the process of telling to
+ * retry a previously failed attempt to perform a timing
+ * transaction. This is a valid port when in the retry state,
+ * and NULL when in busy or idle.
+ */
+ PortClass* retryingPort;
/**
* Release the bus layer after being occupied and return to an
typedef AddrRangeMap<PortID>::const_iterator PortMapConstIter;
AddrRangeMap<PortID> portMap;
- AddrRangeList defaultRange;
+ /** all contigous ranges seen by this bus */
+ AddrRangeList busRanges;
+
+ AddrRange defaultRange;
/**
* Function called by the port when the bus is recieving a range change.
struct PortCache {
bool valid;
PortID id;
- Addr start;
- Addr end;
+ AddrRange range;
};
PortCache portCache[3];
// Checks the cache and returns the id of the port that has the requested
// address within its range
- inline PortID checkPortCache(Addr addr) {
- if (portCache[0].valid && addr >= portCache[0].start &&
- addr < portCache[0].end) {
+ inline PortID checkPortCache(Addr addr) const {
+ if (portCache[0].valid && portCache[0].range.contains(addr)) {
return portCache[0].id;
}
- if (portCache[1].valid && addr >= portCache[1].start &&
- addr < portCache[1].end) {
+ if (portCache[1].valid && portCache[1].range.contains(addr)) {
return portCache[1].id;
}
- if (portCache[2].valid && addr >= portCache[2].start &&
- addr < portCache[2].end) {
+ if (portCache[2].valid && portCache[2].range.contains(addr)) {
return portCache[2].id;
}
}
// Clears the earliest entry of the cache and inserts a new port entry
- inline void updatePortCache(short id, Addr start, Addr end) {
+ inline void updatePortCache(short id, const AddrRange& range) {
portCache[2].valid = portCache[1].valid;
portCache[2].id = portCache[1].id;
- portCache[2].start = portCache[1].start;
- portCache[2].end = portCache[1].end;
+ portCache[2].range = portCache[1].range;
portCache[1].valid = portCache[0].valid;
portCache[1].id = portCache[0].id;
- portCache[1].start = portCache[0].start;
- portCache[1].end = portCache[0].end;
+ portCache[1].range = portCache[0].range;
portCache[0].valid = true;
portCache[0].id = id;
- portCache[0].start = start;
- portCache[0].end = end;
+ portCache[0].range = range;
}
// Clears the cache. Needs to be called in constructor.
*/
AddrRangeList getAddrRanges() const;
- /** Calculate the timing parameters for the packet. Updates the
- * firstWordTime and finishTime fields of the packet object.
- * Returns the tick at which the packet header is completed (which
- * will be all that is sent if the target rejects the packet).
+ /**
+ * Calculate the timing parameters for the packet. Updates the
+ * busFirstWordDelay and busLastWordDelay fields of the packet
+ * object with the relative number of ticks required to transmit
+ * the header and the first word, and the last word, respectively.
*/
- Tick calcPacketTiming(PacketPtr pkt);
+ void calcPacketTiming(PacketPtr pkt);
/**
* Ask everyone on the bus what their size is and determine the
*/
unsigned deviceBlockSize() const;
- std::set<PortID> inRecvRangeChange;
+ /**
+ * Remember for each of the master ports of the bus if we got an
+ * address range from the connected slave. For convenience, also
+ * keep track of if we got ranges from all the slave modules or
+ * not.
+ */
+ std::vector<bool> gotAddrRanges;
+ bool gotAllAddrRanges;
/** The master and slave ports of the bus */
std::vector<SlavePort*> slavePorts;
virtual void init();
/** A function used to return the port associated with this bus object. */
- virtual MasterPort& getMasterPort(const std::string& if_name, int idx = -1);
- virtual SlavePort& getSlavePort(const std::string& if_name, int idx = -1);
+ BaseMasterPort& getMasterPort(const std::string& if_name,
+ PortID idx = InvalidPortID);
+ BaseSlavePort& getSlavePort(const std::string& if_name,
+ PortID idx = InvalidPortID);
- virtual unsigned int drain(Event *de) = 0;
+ virtual unsigned int drain(DrainManager *dm) = 0;
};