* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ * Steve Reinhardt
*/
/**
- * @file Decleration of a simple bus bridge object with no buffering
+ * @file
+ * Declaration of a simple bus bridge object with no buffering
*/
#ifndef __MEM_BRIDGE_HH__
#include <inttypes.h>
#include <queue>
-
+#include "base/fast_alloc.hh"
#include "mem/mem_object.hh"
#include "mem/packet.hh"
#include "mem/port.hh"
+#include "params/Bridge.hh"
#include "sim/eventq.hh"
class Bridge : public MemObject
{
- public:
- enum Side
+ protected:
+ /** Declaration of the buses port type, one will be instantiated for each
+ of the interfaces connecting to the bus. */
+ class BridgePort : public Port
{
- SideA,
- SideB
- };
+ /** A pointer to the bridge to which this port belongs. */
+ Bridge *bridge;
- protected:
- /** Function called by the port when the bus is recieving a Timing
- transaction.*/
- bool recvTiming(Packet *pkt, Side id);
+ /**
+ * Pointer to the port on the other side of the bridge
+ * (connected to the other bus).
+ */
+ BridgePort *otherPort;
- /** Function called by the port when the bus is recieving a Atomic
- transaction.*/
- Tick recvAtomic(Packet *pkt, Side id);
+ /** Minimum delay though this bridge. */
+ Tick delay;
- /** Function called by the port when the bus is recieving a Functional
- transaction.*/
- void recvFunctional(Packet *pkt, Side id);
+ /** Min delay to respond to a nack. */
+ Tick nackDelay;
- /** Function called by the port when the bus is recieving a status change.*/
- void recvStatusChange(Port::Status status, Side id);
+ /** Pass ranges from one side of the bridge to the other? */
+ std::vector<Range<Addr> > filterRanges;
- /** Process address range request.
- * @param resp addresses that we can respond to
- * @param snoop addresses that we would like to snoop
- * @param id ide of the busport that made the request.
- */
- void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, Side id);
+ class PacketBuffer : public Packet::SenderState, public FastAlloc {
+ public:
+ Tick ready;
+ PacketPtr pkt;
+ bool nackedHere;
+ Packet::SenderState *origSenderState;
+ short origSrc;
+ bool expectResponse;
- /** Event that the SendEvent calls when it fires. This code must reschedule
- * the send event as required. */
- void timerEvent();
+ PacketBuffer(PacketPtr _pkt, Tick t, bool nack = false)
+ : ready(t), pkt(_pkt), nackedHere(nack),
+ origSenderState(_pkt->senderState),
+ origSrc(nack ? _pkt->getDest() : _pkt->getSrc() ),
+ expectResponse(_pkt->needsResponse() && !nack)
- /** Decleration of the buses port type, one will be instantiated for each
- of the interfaces connecting to the bus. */
- class BridgePort : public Port
- {
- /** A pointer to the bus to which this port belongs. */
- Bridge *bridge;
+ {
+ if (!pkt->isResponse() && !nack)
+ pkt->senderState = this;
+ }
- /** A id to keep track of the intercafe ID this port is connected to. */
- Bridge::Side side;
+ void fixResponse(PacketPtr pkt)
+ {
+ assert(pkt->senderState == this);
+ pkt->setDest(origSrc);
+ pkt->senderState = origSenderState;
+ }
+ };
- public:
+ /**
+ * Outbound packet queue. Packets are held in this queue for a
+ * specified delay to model the processing delay of the
+ * bridge.
+ */
+ std::list<PacketBuffer*> sendQueue;
- /** Constructor for the BusPort.*/
- BridgePort(Bridge *_bridge, Side _side)
- : bridge(_bridge), side(_side)
- { }
+ int outstandingResponses;
+ int queuedRequests;
- int numQueued() { return outbound.size(); }
+ /** If we're waiting for a retry to happen.*/
+ bool inRetry;
- protected:
- /** Data this is waiting to be transmitted. */
- std::list<std::pair<Packet*, Tick> > outbound;
+ /** Max queue size for outbound packets */
+ int reqQueueLimit;
- void sendPkt(Packet *pkt);
- void sendPkt(std::pair<Packet*, Tick> p);
+ /** Max queue size for reserved responses. */
+ int respQueueLimit;
- /** When reciving a timing request from the peer port,
- pass it to the bridge. */
- virtual bool recvTiming(Packet *pkt)
- { return bridge->recvTiming(pkt, side); }
+ /**
+ * Is this side blocked from accepting outbound packets?
+ */
+ bool respQueueFull();
+ bool reqQueueFull();
- /** When reciving a retry request from the peer port,
- pass it to the bridge. */
- virtual Packet* recvRetry();
+ void queueForSendTiming(PacketPtr pkt);
- /** When reciving a Atomic requestfrom the peer port,
- pass it to the bridge. */
- virtual Tick recvAtomic(Packet *pkt)
- { return bridge->recvAtomic(pkt, side); }
+ void finishSend(PacketBuffer *buf);
- /** When reciving a Functional request from the peer port,
- pass it to the bridge. */
- virtual void recvFunctional(Packet *pkt)
- { bridge->recvFunctional(pkt, side); }
+ void nackRequest(PacketPtr pkt);
- /** When reciving a status changefrom the peer port,
- pass it to the bridge. */
- virtual void recvStatusChange(Status status)
- { bridge->recvStatusChange(status, side); }
+ /**
+ * Handle send event, scheduled when the packet at the head of
+ * the outbound queue is ready to transmit (for timing
+ * accesses only).
+ */
+ void trySend();
- /** When reciving a address range request the peer port,
- pass it to the bridge. */
- virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
- { bridge->addressRanges(resp, snoop, side); }
+ class SendEvent : public Event
+ {
+ BridgePort *port;
- friend class Bridge;
- };
+ public:
+ SendEvent(BridgePort *p) : port(p) {}
+ virtual void process() { port->trySend(); }
+ virtual const char *description() const { return "bridge send"; }
+ };
- class SendEvent : public Event
- {
- Bridge *bridge;
+ SendEvent sendEvent;
- SendEvent(Bridge *b)
- : Event(&mainEventQueue), bridge(b) {}
+ public:
+ /** Constructor for the BusPort.*/
+ BridgePort(const std::string &_name, Bridge *_bridge,
+ BridgePort *_otherPort, int _delay, int _nack_delay,
+ int _req_limit, int _resp_limit,
+ std::vector<Range<Addr> > filter_ranges);
- virtual void process() { bridge->timerEvent(); }
+ protected:
- virtual const char *description() { return "bridge delay event"; }
- friend class Bridge;
- };
+ /** When receiving a timing request from the peer port,
+ pass it to the bridge. */
+ virtual bool recvTiming(PacketPtr pkt);
- SendEvent sendEvent;
+ /** When receiving a retry request from the peer port,
+ pass it to the bridge. */
+ virtual void recvRetry();
- /** Sides of the bus bridges. */
- BridgePort* sideA;
- BridgePort* sideB;
+ /** When receiving a Atomic requestfrom the peer port,
+ pass it to the bridge. */
+ virtual Tick recvAtomic(PacketPtr pkt);
- /** inbound queues on both sides. */
- std::list<std::pair<Packet*, Tick> > inboundA;
- std::list<std::pair<Packet*, Tick> > inboundB;
+ /** When receiving a Functional request from the peer port,
+ pass it to the bridge. */
+ virtual void recvFunctional(PacketPtr pkt);
- /** The size of the queue for data coming into side a */
- int queueSizeA;
- int queueSizeB;
+ /** When receiving a status changefrom the peer port,
+ pass it to the bridge. */
+ virtual void recvStatusChange(Status status);
- /* if the side is blocked or not. */
- bool blockedA;
- bool blockedB;
+ /** When receiving a address range request the peer port,
+ pass it to the bridge. */
+ virtual void getDeviceAddressRanges(AddrRangeList &resp,
+ bool &snoop);
+ };
- /** Miminum delay though this bridge. */
- Tick delay;
+ BridgePort portA, portB;
/** If this bridge should acknowledge writes. */
bool ackWrites;
public:
+ typedef BridgeParams Params;
- /** A function used to return the port associated with this bus object. */
- virtual Port *getPort(const std::string &if_name)
- {
- if (if_name == "side_a") {
- if (sideA != NULL)
- panic("bridge side a already connected to.");
- sideA = new BridgePort(this, SideA);
- return sideA;
- } else if (if_name == "side_b") {
- if (sideB != NULL)
- panic("bridge side b already connected to.");
- sideB = new BridgePort(this, SideB);
- return sideB;
- } else
- return NULL;
- }
-
- virtual void init();
+ protected:
+ Params *_params;
- Bridge(const std::string &n, int qsa, int qsb, Tick _delay, int write_ack)
- : MemObject(n), sendEvent(this), sideA(NULL), sideB(NULL),
- queueSizeA(qsa), queueSizeB(qsb), blockedA(false), blockedB(false),
- delay(_delay), ackWrites(write_ack)
- {}
+ public:
+ const Params *params() const { return _params; }
- /** Check if the port should block/unblock after recieving/sending a packet.
- * */
- void blockCheck(Side id);
+ /** A function used to return the port associated with this bus object. */
+ virtual Port *getPort(const std::string &if_name, int idx = -1);
- friend class Bridge::SendEvent;
+ virtual void init();
+ Bridge(Params *p);
};
#endif //__MEM_BUS_HH__