diff -r a811340109b6 -r f244ad15be32 src/mem/cache/cache_impl.hh --- a/src/mem/cache/cache_impl.hh Mon Jun 15 19:00:37 2015 +0100 +++ b/src/mem/cache/cache_impl.hh Mon Jun 15 19:00:43 2015 +0100 @@ -1172,6 +1172,11 @@ { assert(pkt->isResponse()); + // all header delay should be paid for by the crossbar, unless + // this is a prefetch response from above + panic_if(pkt->headerDelay != 0 && pkt->cmd != MemCmd::HardPFResp, + "%s saw a non-zero packet delay\n", name()); + MSHR *mshr = dynamic_cast(pkt->senderState); bool is_error = pkt->isError(); diff -r a811340109b6 -r f244ad15be32 src/mem/coherent_xbar.hh --- a/src/mem/coherent_xbar.hh Mon Jun 15 19:00:37 2015 +0100 +++ b/src/mem/coherent_xbar.hh Mon Jun 15 19:00:43 2015 +0100 @@ -84,7 +84,7 @@ * be instantiated for each of the master ports connecting to the * crossbar. */ - class CoherentXBarSlavePort : public SlavePort + class CoherentXBarSlavePort : public QueuedSlavePort { private: @@ -92,11 +92,15 @@ /** 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: @@ -126,12 +130,6 @@ { xbar.recvFunctional(pkt, id); } /** - * When receiving a retry, pass it to the crossbar. - */ - virtual void recvRespRetry() - { panic("Crossbar slave ports should never retry.\n"); } - - /** * Return the union of all adress ranges seen by this crossbar. */ virtual AddrRangeList getAddrRanges() const @@ -215,14 +213,14 @@ 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) { } @@ -253,7 +251,7 @@ std::vector snoopRespPorts; - std::vector snoopPorts; + std::vector snoopPorts; /** * Store the outstanding requests that we are expecting snoop @@ -324,7 +322,7 @@ * @param dests Vector of destination ports for the forwarded pkt */ void forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id, - const std::vector& dests); + const std::vector& dests); /** Function called by the port when the crossbar is recieving a Atomic transaction.*/ @@ -347,7 +345,8 @@ std::pair 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); } /** @@ -365,7 +364,8 @@ std::pair forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id, PortID source_master_port_id, - const std::vector& dests); + const std::vector& + dests); /** Function called by the port when the crossbar is recieving a Functional transaction.*/ diff -r a811340109b6 -r f244ad15be32 src/mem/coherent_xbar.cc --- a/src/mem/coherent_xbar.cc Mon Jun 15 19:00:37 2015 +0100 +++ b/src/mem/coherent_xbar.cc Mon Jun 15 19:00:43 2015 +0100 @@ -89,7 +89,7 @@ // create the slave ports, once again starting at zero for (int i = 0; i < p->port_slave_connection_count; ++i) { std::string portName = csprintf("%s.slave[%d]", name(), i); - SlavePort* bp = new CoherentXBarSlavePort(portName, *this, i); + QueuedSlavePort* bp = new CoherentXBarSlavePort(portName, *this, i); slavePorts.push_back(bp); respLayers.push_back(new RespLayer(*bp, *this, csprintf(".respLayer%d", i))); @@ -344,12 +344,11 @@ snoopFilter->updateResponse(pkt, *slavePorts[slave_port_id]); } - // send the packet through the destination slave port - bool success M5_VAR_USED = slavePorts[slave_port_id]->sendTimingResp(pkt); - - // currently it is illegal to block responses... can lead to - // deadlock - assert(success); + // send the packet through the destination slave port and pay for + // any outstanding header delay + Tick latency = pkt->headerDelay; + pkt->headerDelay = 0; + slavePorts[slave_port_id]->schedTimingResp(pkt, curTick() + latency); // remove the request from the routing table routeTo.erase(route_lookup); @@ -516,18 +515,11 @@ pkt->getAddr()); // as a normal response, it should go back to a master through - // one of our slave ports, at this point we are ignoring the - // fact that the response layer could be busy and do not touch - // its state - bool success M5_VAR_USED = - slavePorts[dest_port_id]->sendTimingResp(pkt); - - // @todo Put the response in an internal FIFO and pass it on - // to the response layer from there - - // currently it is illegal to block responses... can lead - // to deadlock - assert(success); + // one of our slave ports, we also pay for any outstanding + // header latency + Tick latency = pkt->headerDelay; + pkt->headerDelay = 0; + slavePorts[dest_port_id]->schedTimingResp(pkt, curTick() + latency); respLayers[dest_port_id]->succeededTiming(packetFinishTime); } @@ -545,7 +537,7 @@ void CoherentXBar::forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id, - const std::vector& dests) + const std::vector& dests) { DPRINTF(CoherentXBar, "%s for %s address %x size %d\n", __func__, pkt->cmdString(), pkt->getAddr(), pkt->getSize()); @@ -699,7 +691,7 @@ std::pair CoherentXBar::forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id, PortID source_master_port_id, - const std::vector& dests) + const std::vector& dests) { // the packet may be changed on snoops, record the original // command to enable us to restore it between snoops so that @@ -786,6 +778,18 @@ // there is no need to continue if the snooping has found what we // were looking for and the packet is already a response if (!pkt->isResponse()) { + // since our slave ports are queued ports we need to check them as well + for (const auto& p : slavePorts) { + // if we find a response that has the data, then the + // downstream caches/memories may be out of date, so simply stop + // here + if (p->checkFunctional(pkt)) { + if (pkt->needsResponse()) + pkt->makeResponse(); + return; + } + } + PortID dest_id = findPort(pkt->getAddr()); masterPorts[dest_id]->sendFunctional(pkt); diff -r a811340109b6 -r f244ad15be32 src/mem/noncoherent_xbar.hh --- a/src/mem/noncoherent_xbar.hh Mon Jun 15 19:00:37 2015 +0100 +++ b/src/mem/noncoherent_xbar.hh Mon Jun 15 19:00:43 2015 +0100 @@ -84,18 +84,22 @@ * will be instantiated for each of the master ports connecting to * the crossbar. */ - class NoncoherentXBarSlavePort : public SlavePort + class NoncoherentXBarSlavePort : public QueuedSlavePort { private: /** A reference to the crossbar to which this port belongs. */ NoncoherentXBar &xbar; + /** A normal packet queue used to store responses. */ + RespPacketQueue queue; + public: NoncoherentXBarSlavePort(const std::string &_name, NoncoherentXBar &_xbar, PortID _id) - : SlavePort(_name, &_xbar, _id), xbar(_xbar) + : QueuedSlavePort(_name, &_xbar, queue, _id), xbar(_xbar), + queue(_xbar, *this) { } protected: @@ -119,12 +123,6 @@ { xbar.recvFunctional(pkt, id); } /** - * When receiving a retry, pass it to the crossbar. - */ - virtual void recvRespRetry() - { panic("Crossbar slave ports should never retry.\n"); } - - /** * Return the union of all adress ranges seen by this crossbar. */ virtual AddrRangeList getAddrRanges() const diff -r a811340109b6 -r f244ad15be32 src/mem/noncoherent_xbar.cc --- a/src/mem/noncoherent_xbar.cc Mon Jun 15 19:00:37 2015 +0100 +++ b/src/mem/noncoherent_xbar.cc Mon Jun 15 19:00:43 2015 +0100 @@ -82,7 +82,7 @@ // create the slave ports, once again starting at zero for (int i = 0; i < p->port_slave_connection_count; ++i) { std::string portName = csprintf("%s.slave[%d]", name(), i); - SlavePort* bp = new NoncoherentXBarSlavePort(portName, *this, i); + QueuedSlavePort* bp = new NoncoherentXBarSlavePort(portName, *this, i); slavePorts.push_back(bp); respLayers.push_back(new RespLayer(*bp, *this, csprintf(".respLayer%d", i))); @@ -218,12 +218,11 @@ // determine how long to be crossbar layer is busy Tick packetFinishTime = clockEdge(Cycles(1)) + pkt->payloadDelay; - // send the packet through the destination slave port - bool success M5_VAR_USED = slavePorts[slave_port_id]->sendTimingResp(pkt); - - // currently it is illegal to block responses... can lead to - // deadlock - assert(success); + // send the packet through the destination slave port, and pay for + // any outstanding latency + Tick latency = pkt->headerDelay; + pkt->headerDelay = 0; + slavePorts[slave_port_id]->schedTimingResp(pkt, curTick() + latency); // remove the request from the routing table routeTo.erase(route_lookup); @@ -295,6 +294,18 @@ pkt->cmdString()); } + // since our slave ports are queued ports we need to check them as well + for (const auto& p : slavePorts) { + // if we find a response that has the data, then the + // downstream caches/memories may be out of date, so simply stop + // here + if (p->checkFunctional(pkt)) { + if (pkt->needsResponse()) + pkt->makeResponse(); + return; + } + } + // determine the destination port PortID dest_id = findPort(pkt->getAddr()); diff -r a811340109b6 -r f244ad15be32 src/mem/snoop_filter.hh --- a/src/mem/snoop_filter.hh Mon Jun 15 19:00:37 2015 +0100 +++ b/src/mem/snoop_filter.hh Mon Jun 15 19:00:43 2015 +0100 @@ -50,6 +50,7 @@ #include "base/hashmap.hh" #include "mem/packet.hh" #include "mem/port.hh" +#include "mem/qport.hh" #include "params/SnoopFilter.hh" #include "sim/sim_object.hh" #include "sim/system.hh" @@ -85,7 +86,7 @@ */ class SnoopFilter : public SimObject { public: - typedef std::vector SnoopList; + typedef std::vector SnoopList; SnoopFilter (const SnoopFilterParams *p) : SimObject(p), linesize(p->system->cacheLineSize()), lookupLatency(p->lookup_latency) @@ -98,7 +99,7 @@ * * @param bus_slave_ports Vector of slave ports that the bus is attached to. */ - void setSlavePorts(const std::vector& bus_slave_ports) { + void setSlavePorts(const SnoopList& bus_slave_ports) { slavePorts = bus_slave_ports; } diff -r a811340109b6 -r f244ad15be32 src/mem/xbar.hh --- a/src/mem/xbar.hh Mon Jun 15 19:00:37 2015 +0100 +++ b/src/mem/xbar.hh Mon Jun 15 19:00:43 2015 +0100 @@ -57,6 +57,7 @@ #include "base/hashmap.hh" #include "base/types.hh" #include "mem/mem_object.hh" +#include "mem/qport.hh" #include "params/BaseXBar.hh" #include "sim/stats.hh" @@ -427,7 +428,7 @@ bool gotAllAddrRanges; /** The master and slave ports of the crossbar */ - std::vector slavePorts; + std::vector slavePorts; std::vector masterPorts; /** Port that handles requests that don't match any of the interfaces.*/