diff options
author | Andreas Hansson <andreas.hansson@arm.com> | 2015-07-03 10:14:44 -0400 |
---|---|---|
committer | Andreas Hansson <andreas.hansson@arm.com> | 2015-07-03 10:14:44 -0400 |
commit | db85ddca1a3c81fb7c513216fa08bb1f6dd580b7 (patch) | |
tree | d4cbaa6a2d2465727e08803e5189993d6493c6d2 /src/mem/coherent_xbar.cc | |
parent | b93c912013cd7f5417b92eaa33010af70e97f8ec (diff) | |
download | gem5-db85ddca1a3c81fb7c513216fa08bb1f6dd580b7.tar.xz |
mem: Delay responses in the crossbar before forwarding
This patch changes how the crossbar classes deal with
responses. Instead of forwarding responses directly and burdening the
neighbouring modules in paying for the latency (through the
pkt->headerDelay), we now queue them before sending them.
The coherency protocol is not affected as requests and any snoop
requests/responses are still passed on in zero time. Thus, the
responses end up paying for any header delay accumulated when passing
through the crossbar. Any latency incurred on the request path will be
paid for on the response side, if no other module has dealt with it.
As a result of this patch, responses are returned at a later
point. This affects the number of outstanding transactions, and quite
a few regressions see an impact in blocking due to no MSHRs, increased
cache-miss latencies, etc.
Going forward we should be able to use the same concept also for snoop
responses, and any request that is not an express snoop.
Diffstat (limited to 'src/mem/coherent_xbar.cc')
-rw-r--r-- | src/mem/coherent_xbar.cc | 46 |
1 files changed, 25 insertions, 21 deletions
diff --git a/src/mem/coherent_xbar.cc b/src/mem/coherent_xbar.cc index b58511db6..7f1639e44 100644 --- a/src/mem/coherent_xbar.cc +++ b/src/mem/coherent_xbar.cc @@ -89,7 +89,7 @@ CoherentXBar::CoherentXBar(const CoherentXBarParams *p) // 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))); @@ -345,12 +345,11 @@ CoherentXBar::recvTimingResp(PacketPtr pkt, PortID master_port_id) 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); @@ -517,18 +516,11 @@ CoherentXBar::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id) 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); } @@ -546,7 +538,7 @@ CoherentXBar::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id) void CoherentXBar::forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id, - const std::vector<SlavePort*>& dests) + const std::vector<QueuedSlavePort*>& dests) { DPRINTF(CoherentXBar, "%s for %s address %x size %d\n", __func__, pkt->cmdString(), pkt->getAddr(), pkt->getSize()); @@ -700,7 +692,7 @@ CoherentXBar::recvAtomicSnoop(PacketPtr pkt, PortID master_port_id) std::pair<MemCmd, Tick> CoherentXBar::forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id, PortID source_master_port_id, - const std::vector<SlavePort*>& dests) + const std::vector<QueuedSlavePort*>& dests) { // the packet may be changed on snoops, record the original // command to enable us to restore it between snoops so that @@ -787,6 +779,18 @@ CoherentXBar::recvFunctional(PacketPtr pkt, PortID slave_port_id) // 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); |