/*
- * Copyright (c) 2011-2014 ARM Limited
+ * Copyright (c) 2011-2015, 2017 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
#ifndef __MEM_COHERENT_XBAR_HH__
#define __MEM_COHERENT_XBAR_HH__
-#include "base/hashmap.hh"
+#include <unordered_set>
+
#include "mem/snoop_filter.hh"
#include "mem/xbar.hh"
#include "params/CoherentXBar.hh"
* Declare the layers of this crossbar, one vector for requests,
* one for responses, and one for snoop responses
*/
- typedef Layer<SlavePort,MasterPort> ReqLayer;
- typedef Layer<MasterPort,SlavePort> RespLayer;
- typedef Layer<SlavePort,MasterPort> SnoopLayer;
std::vector<ReqLayer*> reqLayers;
std::vector<RespLayer*> respLayers;
- std::vector<SnoopLayer*> snoopLayers;
+ std::vector<SnoopRespLayer*> snoopLayers;
/**
* Declaration of the coherent crossbar slave port type, one will
* be instantiated for each of the master ports connecting to the
* crossbar.
*/
- class CoherentXBarSlavePort : public SlavePort
+ class CoherentXBarSlavePort : public QueuedSlavePort
{
private:
/** A reference to the crossbar to which this port belongs. */
CoherentXBar &xbar;
+ /** A normal packet queue used to store responses. */
+ RespPacketQueue queue;
+
public:
CoherentXBarSlavePort(const std::string &_name,
CoherentXBar &_xbar, PortID _id)
- : SlavePort(_name, &_xbar, _id), xbar(_xbar)
+ : QueuedSlavePort(_name, &_xbar, queue, _id), xbar(_xbar),
+ queue(_xbar, *this)
{ }
protected:
virtual void recvFunctional(PacketPtr pkt)
{ xbar.recvFunctional(pkt, id); }
- /**
- * When receiving a retry, pass it to the crossbar.
- */
- virtual void recvRetry()
- { panic("Crossbar slave ports should never retry.\n"); }
-
/**
* Return the union of all adress ranges seen by this crossbar.
*/
/** When reciving a retry from the peer port (at id),
pass it to the crossbar. */
- virtual void recvRetry()
- { xbar.recvRetry(id); }
+ virtual void recvReqRetry()
+ { xbar.recvReqRetry(id); }
};
private:
/** The port which we mirror internally. */
- SlavePort& slavePort;
+ QueuedSlavePort& slavePort;
public:
/**
* Create a snoop response port that mirrors a given slave port.
*/
- SnoopRespPort(SlavePort& slave_port, CoherentXBar& _xbar) :
+ SnoopRespPort(QueuedSlavePort& slave_port, CoherentXBar& _xbar) :
MasterPort(slave_port.name() + ".snoopRespPort", &_xbar),
slavePort(slave_port) { }
* Override the sending of retries and pass them on through
* the mirrored slave port.
*/
- void sendRetry() {
- slavePort.sendRetry();
+ void sendRetryResp() {
+ // forward it as a snoop response retry
+ slavePort.sendRetrySnoopResp();
}
/**
* Provided as necessary.
*/
- void recvRetry() { panic("SnoopRespPort should never see retry\n"); }
+ void recvReqRetry() { panic("SnoopRespPort should never see retry\n"); }
/**
* Provided as necessary.
std::vector<SnoopRespPort*> snoopRespPorts;
- std::vector<SlavePort*> snoopPorts;
+ std::vector<QueuedSlavePort*> snoopPorts;
/**
- * Store the outstanding requests so we can determine which ones
- * we generated and which ones were merely forwarded. This is used
- * in the coherent crossbar when coherency responses come back.
+ * Store the outstanding requests that we are expecting snoop
+ * responses from so we can determine which snoop responses we
+ * generated and which ones were merely forwarded.
*/
- m5::hash_set<RequestPtr> outstandingReq;
+ std::unordered_set<RequestPtr> outstandingSnoop;
/**
* Keep a pointer to the system to be allow to querying memory system
* broadcast needed for probes. NULL denotes an absent filter. */
SnoopFilter *snoopFilter;
+ /** Cycles of snoop response latency.*/
+ const Cycles snoopResponseLatency;
+
+ /** Is this crossbar the point of coherency? **/
+ const bool pointOfCoherency;
+
+ /** Is this crossbar the point of unification? **/
+ const bool pointOfUnification;
+
+ /**
+ * Upstream caches need this packet until true is returned, so
+ * hold it for deletion until a subsequent call
+ */
+ std::unique_ptr<Packet> pendingDelete;
+
/** Function called by the port when the crossbar is recieving a Timing
request packet.*/
bool recvTimingReq(PacketPtr pkt, PortID slave_port_id);
/** Timing function called by port when it is once again able to process
* requests. */
- void recvRetry(PortID master_port_id);
+ void recvReqRetry(PortID master_port_id);
/**
* Forward a timing packet to our snoopers, potentially excluding
* @param dests Vector of destination ports for the forwarded pkt
*/
void forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id,
- const std::vector<SlavePort*>& dests);
+ const std::vector<QueuedSlavePort*>& dests);
/** Function called by the port when the crossbar is recieving a Atomic
transaction.*/
std::pair<MemCmd, Tick> forwardAtomic(PacketPtr pkt,
PortID exclude_slave_port_id)
{
- return forwardAtomic(pkt, exclude_slave_port_id, InvalidPortID, snoopPorts);
+ return forwardAtomic(pkt, exclude_slave_port_id, InvalidPortID,
+ snoopPorts);
}
/**
std::pair<MemCmd, Tick> forwardAtomic(PacketPtr pkt,
PortID exclude_slave_port_id,
PortID source_master_port_id,
- const std::vector<SlavePort*>& dests);
+ const std::vector<QueuedSlavePort*>&
+ dests);
/** Function called by the port when the crossbar is recieving a Functional
transaction.*/
*/
void forwardFunctional(PacketPtr pkt, PortID exclude_slave_port_id);
+ /**
+ * Determine if the crossbar should sink the packet, as opposed to
+ * forwarding it, or responding.
+ */
+ bool sinkPacket(const PacketPtr pkt) const;
+
+ /**
+ * Determine if the crossbar should forward the packet, as opposed to
+ * responding to it.
+ */
+ bool forwardPacket(const PacketPtr pkt);
+
+ /**
+ * Determine if the packet's destination is the memory below
+ *
+ * The memory below is the destination for a cache mainteance
+ * operation to the Point of Coherence/Unification if this is the
+ * Point of Coherence/Unification.
+ *
+ * @param pkt The processed packet
+ *
+ * @return Whether the memory below is the destination for the packet
+ */
+ bool isDestination(const PacketPtr pkt) const
+ {
+ return (pkt->req->isToPOC() && pointOfCoherency) ||
+ (pkt->req->isToPOU() && pointOfUnification);
+ }
+
Stats::Scalar snoops;
+ Stats::Scalar snoopTraffic;
Stats::Distribution snoopFanout;
public:
virtual ~CoherentXBar();
- unsigned int drain(DrainManager *dm);
-
virtual void regStats();
};