diff options
Diffstat (limited to 'src/mem/bridge.hh')
-rw-r--r-- | src/mem/bridge.hh | 332 |
1 files changed, 263 insertions, 69 deletions
diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh index 732717dd4..d389c0a5e 100644 --- a/src/mem/bridge.hh +++ b/src/mem/bridge.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2006 The Regents of The University of Michigan * All rights reserved. * @@ -27,11 +39,13 @@ * * Authors: Ali Saidi * Steve Reinhardt + * Andreas Hansson */ /** * @file - * Declaration of a simple bus bridge object with no buffering + * Declaration of a memory-mapped bus bridge that connects a master + * and a slave through a request and response queue. */ #ifndef __MEM_BRIDGE_HH__ @@ -49,90 +63,232 @@ #include "params/Bridge.hh" #include "sim/eventq.hh" +/** + * A bridge is used to interface two different busses (or in general a + * memory-mapped master and slave), with buffering for requests and + * responses. The bridge has a fixed delay for packets passing through + * it and responds to a fixed set of address ranges. + * + * The bridge comprises a slave port and a master port, that buffer + * outgoing responses and requests respectively. Buffer space is + * reserved when a request arrives, also reserving response space + * before forwarding the request. An incoming request is always + * accepted (recvTiming returns true), but is potentially NACKed if + * there is no request space or response space. + */ class Bridge : public MemObject { protected: - /** Declaration of the buses port type, one will be instantiated for each - of the interfaces connecting to the bus. */ - class BridgePort : public Port + + /** + * A packet buffer stores packets along with their sender state + * and scheduled time for transmission. + */ + class PacketBuffer : public Packet::SenderState, public FastAlloc { + + public: + Tick ready; + PacketPtr pkt; + bool nackedHere; + Packet::SenderState *origSenderState; + short origSrc; + bool expectResponse; + + 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) + + { + if (!pkt->isResponse() && !nack) + pkt->senderState = this; + } + + void fixResponse(PacketPtr pkt) + { + assert(pkt->senderState == this); + pkt->setDest(origSrc); + pkt->senderState = origSenderState; + } + }; + + // Forward declaration to allow the slave port to have a pointer + class BridgeMasterPort; + + /** + * The port on the side that receives requests and sends + * responses. The slave port has a set of address ranges that it + * is responsible for. The slave port also has a buffer for the + * responses not yet sent. + */ + class BridgeSlavePort : public Port { + + private: + /** A pointer to the bridge to which this port belongs. */ Bridge *bridge; /** - * Pointer to the port on the other side of the bridge + * Pointer to the master port on the other side of the bridge * (connected to the other bus). */ - BridgePort *otherPort; + BridgeMasterPort* masterPort; - /** Minimum delay though this bridge. */ + /** Minimum request delay though this bridge. */ Tick delay; - /** Min delay to respond to a nack. */ + /** Min delay to respond with a nack. */ Tick nackDelay; - /** Pass ranges from one side of the bridge to the other? */ - std::vector<Range<Addr> > filterRanges; + /** Address ranges to pass through the bridge */ + AddrRangeList ranges; + + /** + * Response packet queue. Response packets are held in this + * queue for a specified delay to model the processing delay + * of the bridge. + */ + std::list<PacketBuffer*> responseQueue; - class PacketBuffer : public Packet::SenderState, public FastAlloc { + /** Counter to track the outstanding responses. */ + unsigned int outstandingResponses; + + /** If we're waiting for a retry to happen. */ + bool inRetry; + + /** Max queue size for reserved responses. */ + unsigned int respQueueLimit; + + /** + * Is this side blocked from accepting new response packets. + * + * @return true if the reserved space has reached the set limit + */ + bool respQueueFull(); + + /** + * Turn the request packet into a NACK response and put it in + * the response queue and schedule its transmission. + * + * @param pkt the request packet to NACK + */ + void nackRequest(PacketPtr pkt); + + /** + * Handle send event, scheduled when the packet at the head of + * the response queue is ready to transmit (for timing + * accesses only). + */ + void trySend(); + + /** + * Private class for scheduling sending of responses from the + * response queue. + */ + class SendEvent : public Event + { + BridgeSlavePort *port; public: - Tick ready; - PacketPtr pkt; - bool nackedHere; - Packet::SenderState *origSenderState; - short origSrc; - bool expectResponse; - - 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) - - { - if (!pkt->isResponse() && !nack) - pkt->senderState = this; - } - - void fixResponse(PacketPtr pkt) - { - assert(pkt->senderState == this); - pkt->setDest(origSrc); - pkt->senderState = origSenderState; - } + SendEvent(BridgeSlavePort *p) : port(p) {} + virtual void process() { port->trySend(); } + virtual const char *description() const { return "bridge send"; } }; + /** Send event for the response queue. */ + SendEvent sendEvent; + + public: + /** - * Outbound packet queue. Packets are held in this queue for a - * specified delay to model the processing delay of the - * bridge. + * Constructor for the BridgeSlavePort. + * + * @param _name the port name including the owner + * @param _bridge the structural owner + * @param _masterPort the master port on the other side of the bridge + * @param _delay the delay from seeing a response to sending it + * @param _nack_delay the delay from a NACK to sending the response + * @param _resp_limit the size of the response queue + * @param _ranges a number of address ranges to forward */ - std::list<PacketBuffer*> sendQueue; + BridgeSlavePort(const std::string &_name, Bridge *_bridge, + BridgeMasterPort* _masterPort, int _delay, + int _nack_delay, int _resp_limit, + std::vector<Range<Addr> > _ranges); - int outstandingResponses; - int queuedRequests; + /** + * Queue a response packet to be sent out later and also schedule + * a send if necessary. + * + * @param pkt a response to send out after a delay + */ + void queueForSendTiming(PacketPtr pkt); - /** If we're waiting for a retry to happen.*/ - bool inRetry; + protected: - /** Max queue size for outbound packets */ - int reqQueueLimit; + /** When receiving a timing request from the peer port, + pass it to the bridge. */ + virtual bool recvTiming(PacketPtr pkt); - /** Max queue size for reserved responses. */ - int respQueueLimit; + /** When receiving a retry request from the peer port, + pass it to the bridge. */ + virtual void recvRetry(); + + /** When receiving a Atomic requestfrom the peer port, + pass it to the bridge. */ + virtual Tick recvAtomic(PacketPtr pkt); + + /** When receiving a Functional request from the peer port, + pass it to the bridge. */ + virtual void recvFunctional(PacketPtr pkt); /** - * Is this side blocked from accepting outbound packets? + * When receiving a range change on the slave side do nothing. */ - bool respQueueFull(); - bool reqQueueFull(); + virtual void recvRangeChange(); - void queueForSendTiming(PacketPtr pkt); + /** When receiving a address range request the peer port, + pass it to the bridge. */ + virtual AddrRangeList getAddrRanges(); + }; - void finishSend(PacketBuffer *buf); - void nackRequest(PacketPtr pkt); + /** + * Port on the side that forwards requests and receives + * responses. The master port has a buffer for the requests not + * yet sent. + */ + class BridgeMasterPort : public Port + { + + private: + + /** A pointer to the bridge to which this port belongs. */ + Bridge* bridge; + + /** + * Pointer to the slave port on the other side of the bridge + * (connected to the other bus). + */ + BridgeSlavePort* slavePort; + + /** Minimum delay though this bridge. */ + Tick delay; + + /** + * Request packet queue. Request packets are held in this + * queue for a specified delay to model the processing delay + * of the bridge. + */ + std::list<PacketBuffer*> requestQueue; + + /** If we're waiting for a retry to happen. */ + bool inRetry; + + /** Max queue size for request packets */ + unsigned int reqQueueLimit; /** * Handle send event, scheduled when the packet at the head of @@ -141,24 +297,62 @@ class Bridge : public MemObject */ void trySend(); + /** + * Private class for scheduling sending of requests from the + * request queue. + */ class SendEvent : public Event { - BridgePort *port; + BridgeMasterPort *port; public: - SendEvent(BridgePort *p) : port(p) {} + SendEvent(BridgeMasterPort *p) : port(p) {} virtual void process() { port->trySend(); } virtual const char *description() const { return "bridge send"; } }; + /** Send event for the request queue. */ SendEvent sendEvent; 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); + + /** + * Constructor for the BridgeMasterPort. + * + * @param _name the port name including the owner + * @param _bridge the structural owner + * @param _slavePort the slave port on the other side of the bridge + * @param _delay the delay from seeing a request to sending it + * @param _req_limit the size of the request queue + */ + BridgeMasterPort(const std::string &_name, Bridge *_bridge, + BridgeSlavePort* _slavePort, int _delay, + int _req_limit); + + /** + * Is this side blocked from accepting new request packets. + * + * @return true if the occupied space has reached the set limit + */ + bool reqQueueFull(); + + /** + * Queue a request packet to be sent out later and also schedule + * a send if necessary. + * + * @param pkt a request to send out after a delay + */ + void queueForSendTiming(PacketPtr pkt); + + /** + * Check a functional request against the packets in our + * request queue. + * + * @param pkt packet to check against + * + * @return true if we find a match + */ + bool checkFunctional(PacketPtr pkt); protected: @@ -178,17 +372,17 @@ class Bridge : public MemObject pass it to the bridge. */ virtual void recvFunctional(PacketPtr pkt); - /** When receiving a status changefrom the peer port, - pass it to the bridge. */ - virtual void recvStatusChange(Status status); - - /** When receiving a address range request the peer port, - pass it to the bridge. */ - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop); + /** + * When receiving a range change, pass it through the bridge. + */ + virtual void recvRangeChange(); }; - BridgePort portA, portB; + /** Slave port of the bridge. */ + BridgeSlavePort slavePort; + + /** Master port of the bridge. */ + BridgeMasterPort masterPort; /** If this bridge should acknowledge writes. */ bool ackWrites; |