summaryrefslogtreecommitdiff
path: root/src/mem/noncoherent_xbar.cc
diff options
context:
space:
mode:
authorAndreas Hansson <andreas.hansson@arm.com>2015-07-03 10:14:44 -0400
committerAndreas Hansson <andreas.hansson@arm.com>2015-07-03 10:14:44 -0400
commitdb85ddca1a3c81fb7c513216fa08bb1f6dd580b7 (patch)
treed4cbaa6a2d2465727e08803e5189993d6493c6d2 /src/mem/noncoherent_xbar.cc
parentb93c912013cd7f5417b92eaa33010af70e97f8ec (diff)
downloadgem5-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/noncoherent_xbar.cc')
-rw-r--r--src/mem/noncoherent_xbar.cc25
1 files changed, 18 insertions, 7 deletions
diff --git a/src/mem/noncoherent_xbar.cc b/src/mem/noncoherent_xbar.cc
index e2bc85cad..330a91f1f 100644
--- a/src/mem/noncoherent_xbar.cc
+++ b/src/mem/noncoherent_xbar.cc
@@ -82,7 +82,7 @@ NoncoherentXBar::NoncoherentXBar(const NoncoherentXBarParams *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 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 @@ NoncoherentXBar::recvTimingResp(PacketPtr pkt, PortID master_port_id)
// 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 @@ NoncoherentXBar::recvFunctional(PacketPtr pkt, PortID slave_port_id)
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());