coherent_xbar.cc (12346:9b1144d046ca) coherent_xbar.cc (12351:17eaa27bef22)
1/*
2 * Copyright (c) 2011-2017 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 26 unchanged lines hidden (view full) ---

35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Ali Saidi
41 * Andreas Hansson
42 * William Wang
1/*
2 * Copyright (c) 2011-2017 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 26 unchanged lines hidden (view full) ---

35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Ali Saidi
41 * Andreas Hansson
42 * William Wang
43 * Nikos Nikoleris
43 */
44
45/**
46 * @file
47 * Definition of a crossbar object.
48 */
49
50#include "mem/coherent_xbar.hh"

--- 138 unchanged lines hidden (view full) ---

189 // the request
190 const bool is_destination = isDestination(pkt);
191
192 const bool snoop_caches = !system->bypassCaches() &&
193 pkt->cmd != MemCmd::WriteClean;
194 if (snoop_caches) {
195 assert(pkt->snoopDelay == 0);
196
44 */
45
46/**
47 * @file
48 * Definition of a crossbar object.
49 */
50
51#include "mem/coherent_xbar.hh"

--- 138 unchanged lines hidden (view full) ---

190 // the request
191 const bool is_destination = isDestination(pkt);
192
193 const bool snoop_caches = !system->bypassCaches() &&
194 pkt->cmd != MemCmd::WriteClean;
195 if (snoop_caches) {
196 assert(pkt->snoopDelay == 0);
197
198 if (pkt->isClean() && !is_destination) {
199 // before snooping we need to make sure that the memory
200 // below is not busy and the cache clean request can be
201 // forwarded to it
202 if (!masterPorts[master_port_id]->tryTiming(pkt)) {
203 DPRINTF(CoherentXBar, "%s: src %s packet %s RETRY\n", __func__,
204 src_port->name(), pkt->print());
205
206 // update the layer state and schedule an idle event
207 reqLayers[master_port_id]->failedTiming(src_port,
208 clockEdge(Cycles(1)));
209 return false;
210 }
211 }
212
213
197 // the packet is a memory-mapped request and should be
198 // broadcasted to our snoopers but the source
199 if (snoopFilter) {
200 // check with the snoop filter where to forward this packet
201 auto sf_res = snoopFilter->lookupRequest(pkt, *src_port);
202 // the time required by a packet to be delivered through
203 // the xbar has to be charged also with to lookup latency
204 // of the snoop filter

--- 132 unchanged lines hidden (view full) ---

337 snoopTraffic += pkt_size;
338 }
339 }
340
341 if (sink_packet)
342 // queue the packet for deletion
343 pendingDelete.reset(pkt);
344
214 // the packet is a memory-mapped request and should be
215 // broadcasted to our snoopers but the source
216 if (snoopFilter) {
217 // check with the snoop filter where to forward this packet
218 auto sf_res = snoopFilter->lookupRequest(pkt, *src_port);
219 // the time required by a packet to be delivered through
220 // the xbar has to be charged also with to lookup latency
221 // of the snoop filter

--- 132 unchanged lines hidden (view full) ---

354 snoopTraffic += pkt_size;
355 }
356 }
357
358 if (sink_packet)
359 // queue the packet for deletion
360 pendingDelete.reset(pkt);
361
362 // normally we respond to the packet we just received if we need to
363 PacketPtr rsp_pkt = pkt;
364 PortID rsp_port_id = slave_port_id;
365
366 // If this is the destination of the cache clean operation the
367 // crossbar is responsible for responding. This crossbar will
368 // respond when the cache clean is complete. A cache clean
369 // is complete either:
370 // * direcly, if no cache above had a dirty copy of the block
371 // as indicated by the satisfied flag of the packet, or
372 // * when the crossbar has seen both the cache clean request
373 // (CleanSharedReq, CleanInvalidReq) and the corresponding
374 // write (WriteClean) which updates the block in the memory
375 // below.
376 if (success &&
377 ((pkt->isClean() && pkt->satisfied()) ||
378 pkt->cmd == MemCmd::WriteClean) &&
379 is_destination) {
380 PacketPtr deferred_rsp = pkt->isWrite() ? nullptr : pkt;
381 auto cmo_lookup = outstandingCMO.find(pkt->id);
382 if (cmo_lookup != outstandingCMO.end()) {
383 // the cache clean request has already reached this xbar
384 respond_directly = true;
385 if (pkt->isWrite()) {
386 rsp_pkt = cmo_lookup->second;
387 assert(rsp_pkt);
388
389 // determine the destination
390 const auto route_lookup = routeTo.find(rsp_pkt->req);
391 assert(route_lookup != routeTo.end());
392 rsp_port_id = route_lookup->second;
393 assert(rsp_port_id != InvalidPortID);
394 assert(rsp_port_id < respLayers.size());
395 // remove the request from the routing table
396 routeTo.erase(route_lookup);
397 }
398 outstandingCMO.erase(cmo_lookup);
399 } else {
400 respond_directly = false;
401 outstandingCMO.emplace(pkt->id, deferred_rsp);
402 if (!pkt->isWrite()) {
403 assert(routeTo.find(pkt->req) == routeTo.end());
404 routeTo[pkt->req] = slave_port_id;
405
406 panic_if(routeTo.size() > 512,
407 "Routing table exceeds 512 packets\n");
408 }
409 }
410 }
411
412
345 if (respond_directly) {
413 if (respond_directly) {
346 assert(pkt->needsResponse());
414 assert(rsp_pkt->needsResponse());
347 assert(success);
348
415 assert(success);
416
349 pkt->makeResponse();
417 rsp_pkt->makeResponse();
350
351 if (snoopFilter && !system->bypassCaches()) {
352 // let the snoop filter inspect the response and update its state
418
419 if (snoopFilter && !system->bypassCaches()) {
420 // let the snoop filter inspect the response and update its state
353 snoopFilter->updateResponse(pkt, *slavePorts[slave_port_id]);
421 snoopFilter->updateResponse(rsp_pkt, *slavePorts[rsp_port_id]);
354 }
355
422 }
423
424 // we send the response after the current packet, even if the
425 // response is not for this packet (e.g. cache clean operation
426 // where both the request and the write packet have to cross
427 // the destination xbar before the response is sent.)
356 Tick response_time = clockEdge() + pkt->headerDelay;
428 Tick response_time = clockEdge() + pkt->headerDelay;
357 pkt->headerDelay = 0;
429 rsp_pkt->headerDelay = 0;
358
430
359 slavePorts[slave_port_id]->schedTimingResp(pkt, response_time);
431 slavePorts[rsp_port_id]->schedTimingResp(rsp_pkt, response_time);
360 }
361
362 return success;
363}
364
365bool
366CoherentXBar::recvTimingResp(PacketPtr pkt, PortID master_port_id)
367{

--- 381 unchanged lines hidden (view full) ---

749 // if we got a response from a snooper, restore it here
750 if (snoop_response_cmd != MemCmd::InvalidCmd) {
751 // no one else should have responded
752 assert(!pkt->isResponse());
753 pkt->cmd = snoop_response_cmd;
754 response_latency = snoop_response_latency;
755 }
756
432 }
433
434 return success;
435}
436
437bool
438CoherentXBar::recvTimingResp(PacketPtr pkt, PortID master_port_id)
439{

--- 381 unchanged lines hidden (view full) ---

821 // if we got a response from a snooper, restore it here
822 if (snoop_response_cmd != MemCmd::InvalidCmd) {
823 // no one else should have responded
824 assert(!pkt->isResponse());
825 pkt->cmd = snoop_response_cmd;
826 response_latency = snoop_response_latency;
827 }
828
829 // If this is the destination of the cache clean operation the
830 // crossbar is responsible for responding. This crossbar will
831 // respond when the cache clean is complete. An atomic cache clean
832 // is complete when the crossbars receives the cache clean
833 // request (CleanSharedReq, CleanInvalidReq), as either:
834 // * no cache above had a dirty copy of the block as indicated by
835 // the satisfied flag of the packet, or
836 // * the crossbar has already seen the corresponding write
837 // (WriteClean) which updates the block in the memory below.
838 if (pkt->isClean() && isDestination(pkt) && pkt->satisfied()) {
839 auto it = outstandingCMO.find(pkt->id);
840 assert(it != outstandingCMO.end());
841 // we are responding right away
842 outstandingCMO.erase(it);
843 } else if (pkt->cmd == MemCmd::WriteClean && isDestination(pkt)) {
844 // if this is the destination of the operation, the xbar
845 // sends the responce to the cache clean operation only
846 // after having encountered the cache clean request
847 auto M5_VAR_USED ret = outstandingCMO.emplace(pkt->id, nullptr);
848 // in atomic mode we know that the WriteClean packet should
849 // precede the clean request
850 assert(ret.second);
851 }
852
757 // add the response data
758 if (pkt->isResponse()) {
759 pkt_size = pkt->hasData() ? pkt->getSize() : 0;
760 pkt_cmd = pkt->cmdToIndex();
761
762 // stats updates
763 pktCount[slave_port_id][master_port_id]++;
764 pktSize[slave_port_id][master_port_id] += pkt_size;

--- 218 unchanged lines hidden (view full) ---

983 (pkt->cacheResponding() &&
984 (!pkt->needsWritable() || pkt->responderHadWritable()));
985}
986
987bool
988CoherentXBar::forwardPacket(const PacketPtr pkt)
989{
990 // we are forwarding the packet if:
853 // add the response data
854 if (pkt->isResponse()) {
855 pkt_size = pkt->hasData() ? pkt->getSize() : 0;
856 pkt_cmd = pkt->cmdToIndex();
857
858 // stats updates
859 pktCount[slave_port_id][master_port_id]++;
860 pktSize[slave_port_id][master_port_id] += pkt_size;

--- 218 unchanged lines hidden (view full) ---

1079 (pkt->cacheResponding() &&
1080 (!pkt->needsWritable() || pkt->responderHadWritable()));
1081}
1082
1083bool
1084CoherentXBar::forwardPacket(const PacketPtr pkt)
1085{
1086 // we are forwarding the packet if:
991 // 1) this is a read or a write
992 // 2) this crossbar is above the point of coherency
1087 // 1) this is a cache clean request to the PoU/PoC and this
1088 // crossbar is above the PoU/PoC
1089 // 2) this is a read or a write
1090 // 3) this crossbar is above the point of coherency
1091 if (pkt->isClean()) {
1092 return !isDestination(pkt);
1093 }
993 return pkt->isRead() || pkt->isWrite() || !pointOfCoherency;
994}
995
996
997void
998CoherentXBar::regStats()
999{
1000 // register the stats of the base class and our layers

--- 30 unchanged lines hidden ---
1094 return pkt->isRead() || pkt->isWrite() || !pointOfCoherency;
1095}
1096
1097
1098void
1099CoherentXBar::regStats()
1100{
1101 // register the stats of the base class and our layers

--- 30 unchanged lines hidden ---