gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
coherent_xbar.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2019 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
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright (c) 2006 The Regents of The University of Michigan
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions are
19  * met: redistributions of source code must retain the above copyright
20  * notice, this list of conditions and the following disclaimer;
21  * redistributions in binary form must reproduce the above copyright
22  * notice, this list of conditions and the following disclaimer in the
23  * documentation and/or other materials provided with the distribution;
24  * neither the name of the copyright holders nor the names of its
25  * contributors may be used to endorse or promote products derived from
26  * this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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
44  */
45 
51 #include "mem/coherent_xbar.hh"
52 
53 #include "base/logging.hh"
54 #include "base/trace.hh"
55 #include "debug/AddrRanges.hh"
56 #include "debug/CoherentXBar.hh"
57 #include "sim/system.hh"
58 
59 CoherentXBar::CoherentXBar(const CoherentXBarParams *p)
60  : BaseXBar(p), system(p->system), snoopFilter(p->snoop_filter),
61  snoopResponseLatency(p->snoop_response_latency),
62  maxOutstandingSnoopCheck(p->max_outstanding_snoops),
63  maxRoutingTableSizeCheck(p->max_routing_table_size),
64  pointOfCoherency(p->point_of_coherency),
65  pointOfUnification(p->point_of_unification),
66 
67  snoops(this, "snoops", "Total snoops (count)"),
68  snoopTraffic(this, "snoopTraffic", "Total snoop traffic (bytes)"),
69  snoopFanout(this, "snoop_fanout", "Request fanout histogram")
70 {
71  // create the ports based on the size of the master and slave
72  // vector ports, and the presence of the default port, the ports
73  // are enumerated starting from zero
74  for (int i = 0; i < p->port_master_connection_count; ++i) {
75  std::string portName = csprintf("%s.master[%d]", name(), i);
76  MasterPort* bp = new CoherentXBarMasterPort(portName, *this, i);
77  masterPorts.push_back(bp);
78  reqLayers.push_back(new ReqLayer(*bp, *this,
79  csprintf("reqLayer%d", i)));
80  snoopLayers.push_back(
81  new SnoopRespLayer(*bp, *this, csprintf("snoopLayer%d", i)));
82  }
83 
84  // see if we have a default slave device connected and if so add
85  // our corresponding master port
86  if (p->port_default_connection_count) {
87  defaultPortID = masterPorts.size();
88  std::string portName = name() + ".default";
89  MasterPort* bp = new CoherentXBarMasterPort(portName, *this,
91  masterPorts.push_back(bp);
92  reqLayers.push_back(new ReqLayer(*bp, *this, csprintf("reqLayer%d",
93  defaultPortID)));
94  snoopLayers.push_back(new SnoopRespLayer(*bp, *this,
95  csprintf("snoopLayer%d",
96  defaultPortID)));
97  }
98 
99  // create the slave ports, once again starting at zero
100  for (int i = 0; i < p->port_slave_connection_count; ++i) {
101  std::string portName = csprintf("%s.slave[%d]", name(), i);
102  QueuedSlavePort* bp = new CoherentXBarSlavePort(portName, *this, i);
103  slavePorts.push_back(bp);
104  respLayers.push_back(new RespLayer(*bp, *this,
105  csprintf("respLayer%d", i)));
106  snoopRespPorts.push_back(new SnoopRespPort(*bp, *this));
107  }
108 }
109 
111 {
112  for (auto l: reqLayers)
113  delete l;
114  for (auto l: respLayers)
115  delete l;
116  for (auto l: snoopLayers)
117  delete l;
118  for (auto p: snoopRespPorts)
119  delete p;
120 }
121 
122 void
124 {
125  BaseXBar::init();
126 
127  // iterate over our slave ports and determine which of our
128  // neighbouring master ports are snooping and add them as snoopers
129  for (const auto& p: slavePorts) {
130  // check if the connected master port is snooping
131  if (p->isSnooping()) {
132  DPRINTF(AddrRanges, "Adding snooping master %s\n", p->getPeer());
133  snoopPorts.push_back(p);
134  }
135  }
136 
137  if (snoopPorts.empty())
138  warn("CoherentXBar %s has no snooping ports attached!\n", name());
139 
140  // inform the snoop filter about the slave ports so it can create
141  // its own internal representation
142  if (snoopFilter)
143  snoopFilter->setSlavePorts(slavePorts);
144 }
145 
146 bool
148 {
149  // determine the source port based on the id
150  SlavePort *src_port = slavePorts[slave_port_id];
151 
152  // remember if the packet is an express snoop
153  bool is_express_snoop = pkt->isExpressSnoop();
154  bool cache_responding = pkt->cacheResponding();
155  // for normal requests, going downstream, the express snoop flag
156  // and the cache responding flag should always be the same
157  assert(is_express_snoop == cache_responding);
158 
159  // determine the destination based on the destination address range
160  PortID master_port_id = findPort(pkt->getAddrRange());
161 
162  // test if the crossbar should be considered occupied for the current
163  // port, and exclude express snoops from the check
164  if (!is_express_snoop && !reqLayers[master_port_id]->tryTiming(src_port)) {
165  DPRINTF(CoherentXBar, "%s: src %s packet %s BUSY\n", __func__,
166  src_port->name(), pkt->print());
167  return false;
168  }
169 
170  DPRINTF(CoherentXBar, "%s: src %s packet %s\n", __func__,
171  src_port->name(), pkt->print());
172 
173  // store size and command as they might be modified when
174  // forwarding the packet
175  unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
176  unsigned int pkt_cmd = pkt->cmdToIndex();
177 
178  // store the old header delay so we can restore it if needed
179  Tick old_header_delay = pkt->headerDelay;
180 
181  // a request sees the frontend and forward latency
182  Tick xbar_delay = (frontendLatency + forwardLatency) * clockPeriod();
183 
184  // set the packet header and payload delay
185  calcPacketTiming(pkt, xbar_delay);
186 
187  // determine how long to be crossbar layer is busy
188  Tick packetFinishTime = clockEdge(Cycles(1)) + pkt->payloadDelay;
189 
190  // is this the destination point for this packet? (e.g. true if
191  // this xbar is the PoC for a cache maintenance operation to the
192  // PoC) otherwise the destination is any cache that can satisfy
193  // the request
194  const bool is_destination = isDestination(pkt);
195 
196  const bool snoop_caches = !system->bypassCaches() &&
197  pkt->cmd != MemCmd::WriteClean;
198  if (snoop_caches) {
199  assert(pkt->snoopDelay == 0);
200 
201  if (pkt->isClean() && !is_destination) {
202  // before snooping we need to make sure that the memory
203  // below is not busy and the cache clean request can be
204  // forwarded to it
205  if (!masterPorts[master_port_id]->tryTiming(pkt)) {
206  DPRINTF(CoherentXBar, "%s: src %s packet %s RETRY\n", __func__,
207  src_port->name(), pkt->print());
208 
209  // update the layer state and schedule an idle event
210  reqLayers[master_port_id]->failedTiming(src_port,
211  clockEdge(Cycles(1)));
212  return false;
213  }
214  }
215 
216 
217  // the packet is a memory-mapped request and should be
218  // broadcasted to our snoopers but the source
219  if (snoopFilter) {
220  // check with the snoop filter where to forward this packet
221  auto sf_res = snoopFilter->lookupRequest(pkt, *src_port);
222  // the time required by a packet to be delivered through
223  // the xbar has to be charged also with to lookup latency
224  // of the snoop filter
225  pkt->headerDelay += sf_res.second * clockPeriod();
226  DPRINTF(CoherentXBar, "%s: src %s packet %s SF size: %i lat: %i\n",
227  __func__, src_port->name(), pkt->print(),
228  sf_res.first.size(), sf_res.second);
229 
230  if (pkt->isEviction()) {
231  // for block-evicting packets, i.e. writebacks and
232  // clean evictions, there is no need to snoop up, as
233  // all we do is determine if the block is cached or
234  // not, instead just set it here based on the snoop
235  // filter result
236  if (!sf_res.first.empty())
237  pkt->setBlockCached();
238  } else {
239  forwardTiming(pkt, slave_port_id, sf_res.first);
240  }
241  } else {
242  forwardTiming(pkt, slave_port_id);
243  }
244 
245  // add the snoop delay to our header delay, and then reset it
246  pkt->headerDelay += pkt->snoopDelay;
247  pkt->snoopDelay = 0;
248  }
249 
250  // set up a sensible starting point
251  bool success = true;
252 
253  // remember if the packet will generate a snoop response by
254  // checking if a cache set the cacheResponding flag during the
255  // snooping above
256  const bool expect_snoop_resp = !cache_responding && pkt->cacheResponding();
257  bool expect_response = pkt->needsResponse() && !pkt->cacheResponding();
258 
259  const bool sink_packet = sinkPacket(pkt);
260 
261  // in certain cases the crossbar is responsible for responding
262  bool respond_directly = false;
263  // store the original address as an address mapper could possibly
264  // modify the address upon a sendTimingRequest
265  const Addr addr(pkt->getAddr());
266  if (sink_packet) {
267  DPRINTF(CoherentXBar, "%s: Not forwarding %s\n", __func__,
268  pkt->print());
269  } else {
270  // determine if we are forwarding the packet, or responding to
271  // it
272  if (forwardPacket(pkt)) {
273  // if we are passing on, rather than sinking, a packet to
274  // which an upstream cache has committed to responding,
275  // the line was needs writable, and the responding only
276  // had an Owned copy, so we need to immidiately let the
277  // downstream caches know, bypass any flow control
278  if (pkt->cacheResponding()) {
279  pkt->setExpressSnoop();
280  }
281 
282  // make sure that the write request (e.g., WriteClean)
283  // will stop at the memory below if this crossbar is its
284  // destination
285  if (pkt->isWrite() && is_destination) {
286  pkt->clearWriteThrough();
287  }
288 
289  // since it is a normal request, attempt to send the packet
290  success = masterPorts[master_port_id]->sendTimingReq(pkt);
291  } else {
292  // no need to forward, turn this packet around and respond
293  // directly
294  assert(pkt->needsResponse());
295 
296  respond_directly = true;
297  assert(!expect_snoop_resp);
298  expect_response = false;
299  }
300  }
301 
302  if (snoopFilter && snoop_caches) {
303  // Let the snoop filter know about the success of the send operation
304  snoopFilter->finishRequest(!success, addr, pkt->isSecure());
305  }
306 
307  // check if we were successful in sending the packet onwards
308  if (!success) {
309  // express snoops should never be forced to retry
310  assert(!is_express_snoop);
311 
312  // restore the header delay
313  pkt->headerDelay = old_header_delay;
314 
315  DPRINTF(CoherentXBar, "%s: src %s packet %s RETRY\n", __func__,
316  src_port->name(), pkt->print());
317 
318  // update the layer state and schedule an idle event
319  reqLayers[master_port_id]->failedTiming(src_port,
320  clockEdge(Cycles(1)));
321  } else {
322  // express snoops currently bypass the crossbar state entirely
323  if (!is_express_snoop) {
324  // if this particular request will generate a snoop
325  // response
326  if (expect_snoop_resp) {
327  // we should never have an exsiting request outstanding
328  assert(outstandingSnoop.find(pkt->req) ==
329  outstandingSnoop.end());
330  outstandingSnoop.insert(pkt->req);
331 
332  // basic sanity check on the outstanding snoops
334  "%s: Outstanding snoop requests exceeded %d\n",
336  }
337 
338  // remember where to route the normal response to
339  if (expect_response || expect_snoop_resp) {
340  assert(routeTo.find(pkt->req) == routeTo.end());
341  routeTo[pkt->req] = slave_port_id;
342 
343  panic_if(routeTo.size() > maxRoutingTableSizeCheck,
344  "%s: Routing table exceeds %d packets\n",
346  }
347 
348  // update the layer state and schedule an idle event
349  reqLayers[master_port_id]->succeededTiming(packetFinishTime);
350  }
351 
352  // stats updates only consider packets that were successfully sent
353  pktCount[slave_port_id][master_port_id]++;
354  pktSize[slave_port_id][master_port_id] += pkt_size;
355  transDist[pkt_cmd]++;
356 
357  if (is_express_snoop) {
358  snoops++;
359  snoopTraffic += pkt_size;
360  }
361  }
362 
363  if (sink_packet)
364  // queue the packet for deletion
365  pendingDelete.reset(pkt);
366 
367  // normally we respond to the packet we just received if we need to
368  PacketPtr rsp_pkt = pkt;
369  PortID rsp_port_id = slave_port_id;
370 
371  // If this is the destination of the cache clean operation the
372  // crossbar is responsible for responding. This crossbar will
373  // respond when the cache clean is complete. A cache clean
374  // is complete either:
375  // * direcly, if no cache above had a dirty copy of the block
376  // as indicated by the satisfied flag of the packet, or
377  // * when the crossbar has seen both the cache clean request
378  // (CleanSharedReq, CleanInvalidReq) and the corresponding
379  // write (WriteClean) which updates the block in the memory
380  // below.
381  if (success &&
382  ((pkt->isClean() && pkt->satisfied()) ||
383  pkt->cmd == MemCmd::WriteClean) &&
384  is_destination) {
385  PacketPtr deferred_rsp = pkt->isWrite() ? nullptr : pkt;
386  auto cmo_lookup = outstandingCMO.find(pkt->id);
387  if (cmo_lookup != outstandingCMO.end()) {
388  // the cache clean request has already reached this xbar
389  respond_directly = true;
390  if (pkt->isWrite()) {
391  rsp_pkt = cmo_lookup->second;
392  assert(rsp_pkt);
393 
394  // determine the destination
395  const auto route_lookup = routeTo.find(rsp_pkt->req);
396  assert(route_lookup != routeTo.end());
397  rsp_port_id = route_lookup->second;
398  assert(rsp_port_id != InvalidPortID);
399  assert(rsp_port_id < respLayers.size());
400  // remove the request from the routing table
401  routeTo.erase(route_lookup);
402  }
403  outstandingCMO.erase(cmo_lookup);
404  } else {
405  respond_directly = false;
406  outstandingCMO.emplace(pkt->id, deferred_rsp);
407  if (!pkt->isWrite()) {
408  assert(routeTo.find(pkt->req) == routeTo.end());
409  routeTo[pkt->req] = slave_port_id;
410 
411  panic_if(routeTo.size() > maxRoutingTableSizeCheck,
412  "%s: Routing table exceeds %d packets\n",
414  }
415  }
416  }
417 
418 
419  if (respond_directly) {
420  assert(rsp_pkt->needsResponse());
421  assert(success);
422 
423  rsp_pkt->makeResponse();
424 
425  if (snoopFilter && !system->bypassCaches()) {
426  // let the snoop filter inspect the response and update its state
427  snoopFilter->updateResponse(rsp_pkt, *slavePorts[rsp_port_id]);
428  }
429 
430  // we send the response after the current packet, even if the
431  // response is not for this packet (e.g. cache clean operation
432  // where both the request and the write packet have to cross
433  // the destination xbar before the response is sent.)
434  Tick response_time = clockEdge() + pkt->headerDelay;
435  rsp_pkt->headerDelay = 0;
436 
437  slavePorts[rsp_port_id]->schedTimingResp(rsp_pkt, response_time);
438  }
439 
440  return success;
441 }
442 
443 bool
445 {
446  // determine the source port based on the id
447  MasterPort *src_port = masterPorts[master_port_id];
448 
449  // determine the destination
450  const auto route_lookup = routeTo.find(pkt->req);
451  assert(route_lookup != routeTo.end());
452  const PortID slave_port_id = route_lookup->second;
453  assert(slave_port_id != InvalidPortID);
454  assert(slave_port_id < respLayers.size());
455 
456  // test if the crossbar should be considered occupied for the
457  // current port
458  if (!respLayers[slave_port_id]->tryTiming(src_port)) {
459  DPRINTF(CoherentXBar, "%s: src %s packet %s BUSY\n", __func__,
460  src_port->name(), pkt->print());
461  return false;
462  }
463 
464  DPRINTF(CoherentXBar, "%s: src %s packet %s\n", __func__,
465  src_port->name(), pkt->print());
466 
467  // store size and command as they might be modified when
468  // forwarding the packet
469  unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
470  unsigned int pkt_cmd = pkt->cmdToIndex();
471 
472  // a response sees the response latency
473  Tick xbar_delay = responseLatency * clockPeriod();
474 
475  // set the packet header and payload delay
476  calcPacketTiming(pkt, xbar_delay);
477 
478  // determine how long to be crossbar layer is busy
479  Tick packetFinishTime = clockEdge(Cycles(1)) + pkt->payloadDelay;
480 
481  if (snoopFilter && !system->bypassCaches()) {
482  // let the snoop filter inspect the response and update its state
483  snoopFilter->updateResponse(pkt, *slavePorts[slave_port_id]);
484  }
485 
486  // send the packet through the destination slave port and pay for
487  // any outstanding header delay
488  Tick latency = pkt->headerDelay;
489  pkt->headerDelay = 0;
490  slavePorts[slave_port_id]->schedTimingResp(pkt, curTick() + latency);
491 
492  // remove the request from the routing table
493  routeTo.erase(route_lookup);
494 
495  respLayers[slave_port_id]->succeededTiming(packetFinishTime);
496 
497  // stats updates
498  pktCount[slave_port_id][master_port_id]++;
499  pktSize[slave_port_id][master_port_id] += pkt_size;
500  transDist[pkt_cmd]++;
501 
502  return true;
503 }
504 
505 void
507 {
508  DPRINTF(CoherentXBar, "%s: src %s packet %s\n", __func__,
509  masterPorts[master_port_id]->name(), pkt->print());
510 
511  // update stats here as we know the forwarding will succeed
512  unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
513  transDist[pkt->cmdToIndex()]++;
514  snoops++;
515  snoopTraffic += pkt_size;
516 
517  // we should only see express snoops from caches
518  assert(pkt->isExpressSnoop());
519 
520  // set the packet header and payload delay, for now use forward latency
521  // @todo Assess the choice of latency further
523 
524  // remember if a cache has already committed to responding so we
525  // can see if it changes during the snooping
526  const bool cache_responding = pkt->cacheResponding();
527 
528  assert(pkt->snoopDelay == 0);
529 
530  if (snoopFilter) {
531  // let the Snoop Filter work its magic and guide probing
532  auto sf_res = snoopFilter->lookupSnoop(pkt);
533  // the time required by a packet to be delivered through
534  // the xbar has to be charged also with to lookup latency
535  // of the snoop filter
536  pkt->headerDelay += sf_res.second * clockPeriod();
537  DPRINTF(CoherentXBar, "%s: src %s packet %s SF size: %i lat: %i\n",
538  __func__, masterPorts[master_port_id]->name(), pkt->print(),
539  sf_res.first.size(), sf_res.second);
540 
541  // forward to all snoopers
542  forwardTiming(pkt, InvalidPortID, sf_res.first);
543  } else {
545  }
546 
547  // add the snoop delay to our header delay, and then reset it
548  pkt->headerDelay += pkt->snoopDelay;
549  pkt->snoopDelay = 0;
550 
551  // if we can expect a response, remember how to route it
552  if (!cache_responding && pkt->cacheResponding()) {
553  assert(routeTo.find(pkt->req) == routeTo.end());
554  routeTo[pkt->req] = master_port_id;
555  }
556 
557  // a snoop request came from a connected slave device (one of
558  // our master ports), and if it is not coming from the slave
559  // device responsible for the address range something is
560  // wrong, hence there is nothing further to do as the packet
561  // would be going back to where it came from
562  assert(findPort(pkt->getAddrRange()) == master_port_id);
563 }
564 
565 bool
567 {
568  // determine the source port based on the id
569  SlavePort* src_port = slavePorts[slave_port_id];
570 
571  // get the destination
572  const auto route_lookup = routeTo.find(pkt->req);
573  assert(route_lookup != routeTo.end());
574  const PortID dest_port_id = route_lookup->second;
575  assert(dest_port_id != InvalidPortID);
576 
577  // determine if the response is from a snoop request we
578  // created as the result of a normal request (in which case it
579  // should be in the outstandingSnoop), or if we merely forwarded
580  // someone else's snoop request
581  const bool forwardAsSnoop = outstandingSnoop.find(pkt->req) ==
582  outstandingSnoop.end();
583 
584  // test if the crossbar should be considered occupied for the
585  // current port, note that the check is bypassed if the response
586  // is being passed on as a normal response since this is occupying
587  // the response layer rather than the snoop response layer
588  if (forwardAsSnoop) {
589  assert(dest_port_id < snoopLayers.size());
590  if (!snoopLayers[dest_port_id]->tryTiming(src_port)) {
591  DPRINTF(CoherentXBar, "%s: src %s packet %s BUSY\n", __func__,
592  src_port->name(), pkt->print());
593  return false;
594  }
595  } else {
596  // get the master port that mirrors this slave port internally
597  MasterPort* snoop_port = snoopRespPorts[slave_port_id];
598  assert(dest_port_id < respLayers.size());
599  if (!respLayers[dest_port_id]->tryTiming(snoop_port)) {
600  DPRINTF(CoherentXBar, "%s: src %s packet %s BUSY\n", __func__,
601  snoop_port->name(), pkt->print());
602  return false;
603  }
604  }
605 
606  DPRINTF(CoherentXBar, "%s: src %s packet %s\n", __func__,
607  src_port->name(), pkt->print());
608 
609  // store size and command as they might be modified when
610  // forwarding the packet
611  unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
612  unsigned int pkt_cmd = pkt->cmdToIndex();
613 
614  // responses are never express snoops
615  assert(!pkt->isExpressSnoop());
616 
617  // a snoop response sees the snoop response latency, and if it is
618  // forwarded as a normal response, the response latency
619  Tick xbar_delay =
620  (forwardAsSnoop ? snoopResponseLatency : responseLatency) *
621  clockPeriod();
622 
623  // set the packet header and payload delay
624  calcPacketTiming(pkt, xbar_delay);
625 
626  // determine how long to be crossbar layer is busy
627  Tick packetFinishTime = clockEdge(Cycles(1)) + pkt->payloadDelay;
628 
629  // forward it either as a snoop response or a normal response
630  if (forwardAsSnoop) {
631  // this is a snoop response to a snoop request we forwarded,
632  // e.g. coming from the L1 and going to the L2, and it should
633  // be forwarded as a snoop response
634 
635  if (snoopFilter) {
636  // update the probe filter so that it can properly track the line
637  snoopFilter->updateSnoopForward(pkt, *slavePorts[slave_port_id],
638  *masterPorts[dest_port_id]);
639  }
640 
641  bool success M5_VAR_USED =
642  masterPorts[dest_port_id]->sendTimingSnoopResp(pkt);
643  pktCount[slave_port_id][dest_port_id]++;
644  pktSize[slave_port_id][dest_port_id] += pkt_size;
645  assert(success);
646 
647  snoopLayers[dest_port_id]->succeededTiming(packetFinishTime);
648  } else {
649  // we got a snoop response on one of our slave ports,
650  // i.e. from a coherent master connected to the crossbar, and
651  // since we created the snoop request as part of recvTiming,
652  // this should now be a normal response again
653  outstandingSnoop.erase(pkt->req);
654 
655  // this is a snoop response from a coherent master, hence it
656  // should never go back to where the snoop response came from,
657  // but instead to where the original request came from
658  assert(slave_port_id != dest_port_id);
659 
660  if (snoopFilter) {
661  // update the probe filter so that it can properly track the line
662  snoopFilter->updateSnoopResponse(pkt, *slavePorts[slave_port_id],
663  *slavePorts[dest_port_id]);
664  }
665 
666  DPRINTF(CoherentXBar, "%s: src %s packet %s FWD RESP\n", __func__,
667  src_port->name(), pkt->print());
668 
669  // as a normal response, it should go back to a master through
670  // one of our slave ports, we also pay for any outstanding
671  // header latency
672  Tick latency = pkt->headerDelay;
673  pkt->headerDelay = 0;
674  slavePorts[dest_port_id]->schedTimingResp(pkt, curTick() + latency);
675 
676  respLayers[dest_port_id]->succeededTiming(packetFinishTime);
677  }
678 
679  // remove the request from the routing table
680  routeTo.erase(route_lookup);
681 
682  // stats updates
683  transDist[pkt_cmd]++;
684  snoops++;
685  snoopTraffic += pkt_size;
686 
687  return true;
688 }
689 
690 
691 void
692 CoherentXBar::forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id,
693  const std::vector<QueuedSlavePort*>& dests)
694 {
695  DPRINTF(CoherentXBar, "%s for %s\n", __func__, pkt->print());
696 
697  // snoops should only happen if the system isn't bypassing caches
698  assert(!system->bypassCaches());
699 
700  unsigned fanout = 0;
701 
702  for (const auto& p: dests) {
703  // we could have gotten this request from a snooping master
704  // (corresponding to our own slave port that is also in
705  // snoopPorts) and should not send it back to where it came
706  // from
707  if (exclude_slave_port_id == InvalidPortID ||
708  p->getId() != exclude_slave_port_id) {
709  // cache is not allowed to refuse snoop
710  p->sendTimingSnoopReq(pkt);
711  fanout++;
712  }
713  }
714 
715  // Stats for fanout of this forward operation
716  snoopFanout.sample(fanout);
717 }
718 
719 void
721 {
722  // responses and snoop responses never block on forwarding them,
723  // so the retry will always be coming from a port to which we
724  // tried to forward a request
725  reqLayers[master_port_id]->recvRetry();
726 }
727 
728 Tick
730  MemBackdoorPtr *backdoor)
731 {
732  DPRINTF(CoherentXBar, "%s: src %s packet %s\n", __func__,
733  slavePorts[slave_port_id]->name(), pkt->print());
734 
735  unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
736  unsigned int pkt_cmd = pkt->cmdToIndex();
737 
738  MemCmd snoop_response_cmd = MemCmd::InvalidCmd;
739  Tick snoop_response_latency = 0;
740 
741  // is this the destination point for this packet? (e.g. true if
742  // this xbar is the PoC for a cache maintenance operation to the
743  // PoC) otherwise the destination is any cache that can satisfy
744  // the request
745  const bool is_destination = isDestination(pkt);
746 
747  const bool snoop_caches = !system->bypassCaches() &&
748  pkt->cmd != MemCmd::WriteClean;
749  if (snoop_caches) {
750  // forward to all snoopers but the source
751  std::pair<MemCmd, Tick> snoop_result;
752  if (snoopFilter) {
753  // check with the snoop filter where to forward this packet
754  auto sf_res =
755  snoopFilter->lookupRequest(pkt, *slavePorts[slave_port_id]);
756  snoop_response_latency += sf_res.second * clockPeriod();
757  DPRINTF(CoherentXBar, "%s: src %s packet %s SF size: %i lat: %i\n",
758  __func__, slavePorts[slave_port_id]->name(), pkt->print(),
759  sf_res.first.size(), sf_res.second);
760 
761  // let the snoop filter know about the success of the send
762  // operation, and do it even before sending it onwards to
763  // avoid situations where atomic upward snoops sneak in
764  // between and change the filter state
765  snoopFilter->finishRequest(false, pkt->getAddr(), pkt->isSecure());
766 
767  if (pkt->isEviction()) {
768  // for block-evicting packets, i.e. writebacks and
769  // clean evictions, there is no need to snoop up, as
770  // all we do is determine if the block is cached or
771  // not, instead just set it here based on the snoop
772  // filter result
773  if (!sf_res.first.empty())
774  pkt->setBlockCached();
775  } else {
776  snoop_result = forwardAtomic(pkt, slave_port_id, InvalidPortID,
777  sf_res.first);
778  }
779  } else {
780  snoop_result = forwardAtomic(pkt, slave_port_id);
781  }
782  snoop_response_cmd = snoop_result.first;
783  snoop_response_latency += snoop_result.second;
784  }
785 
786  // set up a sensible default value
787  Tick response_latency = 0;
788 
789  const bool sink_packet = sinkPacket(pkt);
790 
791  // even if we had a snoop response, we must continue and also
792  // perform the actual request at the destination
793  PortID master_port_id = findPort(pkt->getAddrRange());
794 
795  if (sink_packet) {
796  DPRINTF(CoherentXBar, "%s: Not forwarding %s\n", __func__,
797  pkt->print());
798  } else {
799  if (forwardPacket(pkt)) {
800  // make sure that the write request (e.g., WriteClean)
801  // will stop at the memory below if this crossbar is its
802  // destination
803  if (pkt->isWrite() && is_destination) {
804  pkt->clearWriteThrough();
805  }
806 
807  // forward the request to the appropriate destination
808  auto master = masterPorts[master_port_id];
809  response_latency = backdoor ?
810  master->sendAtomicBackdoor(pkt, *backdoor) :
811  master->sendAtomic(pkt);
812  } else {
813  // if it does not need a response we sink the packet above
814  assert(pkt->needsResponse());
815 
816  pkt->makeResponse();
817  }
818  }
819 
820  // stats updates for the request
821  pktCount[slave_port_id][master_port_id]++;
822  pktSize[slave_port_id][master_port_id] += pkt_size;
823  transDist[pkt_cmd]++;
824 
825 
826  // if lower levels have replied, tell the snoop filter
827  if (!system->bypassCaches() && snoopFilter && pkt->isResponse()) {
828  snoopFilter->updateResponse(pkt, *slavePorts[slave_port_id]);
829  }
830 
831  // if we got a response from a snooper, restore it here
832  if (snoop_response_cmd != MemCmd::InvalidCmd) {
833  // no one else should have responded
834  assert(!pkt->isResponse());
835  pkt->cmd = snoop_response_cmd;
836  response_latency = snoop_response_latency;
837  }
838 
839  // If this is the destination of the cache clean operation the
840  // crossbar is responsible for responding. This crossbar will
841  // respond when the cache clean is complete. An atomic cache clean
842  // is complete when the crossbars receives the cache clean
843  // request (CleanSharedReq, CleanInvalidReq), as either:
844  // * no cache above had a dirty copy of the block as indicated by
845  // the satisfied flag of the packet, or
846  // * the crossbar has already seen the corresponding write
847  // (WriteClean) which updates the block in the memory below.
848  if (pkt->isClean() && isDestination(pkt) && pkt->satisfied()) {
849  auto it = outstandingCMO.find(pkt->id);
850  assert(it != outstandingCMO.end());
851  // we are responding right away
852  outstandingCMO.erase(it);
853  } else if (pkt->cmd == MemCmd::WriteClean && isDestination(pkt)) {
854  // if this is the destination of the operation, the xbar
855  // sends the responce to the cache clean operation only
856  // after having encountered the cache clean request
857  auto M5_VAR_USED ret = outstandingCMO.emplace(pkt->id, nullptr);
858  // in atomic mode we know that the WriteClean packet should
859  // precede the clean request
860  assert(ret.second);
861  }
862 
863  // add the response data
864  if (pkt->isResponse()) {
865  pkt_size = pkt->hasData() ? pkt->getSize() : 0;
866  pkt_cmd = pkt->cmdToIndex();
867 
868  // stats updates
869  pktCount[slave_port_id][master_port_id]++;
870  pktSize[slave_port_id][master_port_id] += pkt_size;
871  transDist[pkt_cmd]++;
872  }
873 
874  // @todo: Not setting header time
875  pkt->payloadDelay = response_latency;
876  return response_latency;
877 }
878 
879 Tick
881 {
882  DPRINTF(CoherentXBar, "%s: src %s packet %s\n", __func__,
883  masterPorts[master_port_id]->name(), pkt->print());
884 
885  // add the request snoop data
886  unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
887  snoops++;
888  snoopTraffic += pkt_size;
889 
890  // forward to all snoopers
891  std::pair<MemCmd, Tick> snoop_result;
892  Tick snoop_response_latency = 0;
893  if (snoopFilter) {
894  auto sf_res = snoopFilter->lookupSnoop(pkt);
895  snoop_response_latency += sf_res.second * clockPeriod();
896  DPRINTF(CoherentXBar, "%s: src %s packet %s SF size: %i lat: %i\n",
897  __func__, masterPorts[master_port_id]->name(), pkt->print(),
898  sf_res.first.size(), sf_res.second);
899  snoop_result = forwardAtomic(pkt, InvalidPortID, master_port_id,
900  sf_res.first);
901  } else {
902  snoop_result = forwardAtomic(pkt, InvalidPortID);
903  }
904  MemCmd snoop_response_cmd = snoop_result.first;
905  snoop_response_latency += snoop_result.second;
906 
907  if (snoop_response_cmd != MemCmd::InvalidCmd)
908  pkt->cmd = snoop_response_cmd;
909 
910  // add the response snoop data
911  if (pkt->isResponse()) {
912  snoops++;
913  }
914 
915  // @todo: Not setting header time
916  pkt->payloadDelay = snoop_response_latency;
917  return snoop_response_latency;
918 }
919 
921 CoherentXBar::forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id,
922  PortID source_master_port_id,
923  const std::vector<QueuedSlavePort*>& dests)
924 {
925  // the packet may be changed on snoops, record the original
926  // command to enable us to restore it between snoops so that
927  // additional snoops can take place properly
928  MemCmd orig_cmd = pkt->cmd;
929  MemCmd snoop_response_cmd = MemCmd::InvalidCmd;
930  Tick snoop_response_latency = 0;
931 
932  // snoops should only happen if the system isn't bypassing caches
933  assert(!system->bypassCaches());
934 
935  unsigned fanout = 0;
936 
937  for (const auto& p: dests) {
938  // we could have gotten this request from a snooping master
939  // (corresponding to our own slave port that is also in
940  // snoopPorts) and should not send it back to where it came
941  // from
942  if (exclude_slave_port_id != InvalidPortID &&
943  p->getId() == exclude_slave_port_id)
944  continue;
945 
946  Tick latency = p->sendAtomicSnoop(pkt);
947  fanout++;
948 
949  // in contrast to a functional access, we have to keep on
950  // going as all snoopers must be updated even if we get a
951  // response
952  if (!pkt->isResponse())
953  continue;
954 
955  // response from snoop agent
956  assert(pkt->cmd != orig_cmd);
957  assert(pkt->cacheResponding());
958  // should only happen once
959  assert(snoop_response_cmd == MemCmd::InvalidCmd);
960  // save response state
961  snoop_response_cmd = pkt->cmd;
962  snoop_response_latency = latency;
963 
964  if (snoopFilter) {
965  // Handle responses by the snoopers and differentiate between
966  // responses to requests from above and snoops from below
967  if (source_master_port_id != InvalidPortID) {
968  // Getting a response for a snoop from below
969  assert(exclude_slave_port_id == InvalidPortID);
971  *masterPorts[source_master_port_id]);
972  } else {
973  // Getting a response for a request from above
974  assert(source_master_port_id == InvalidPortID);
976  *slavePorts[exclude_slave_port_id]);
977  }
978  }
979  // restore original packet state for remaining snoopers
980  pkt->cmd = orig_cmd;
981  }
982 
983  // Stats for fanout
984  snoopFanout.sample(fanout);
985 
986  // the packet is restored as part of the loop and any potential
987  // snoop response is part of the returned pair
988  return std::make_pair(snoop_response_cmd, snoop_response_latency);
989 }
990 
991 void
993 {
994  if (!pkt->isPrint()) {
995  // don't do DPRINTFs on PrintReq as it clutters up the output
996  DPRINTF(CoherentXBar, "%s: src %s packet %s\n", __func__,
997  slavePorts[slave_port_id]->name(), pkt->print());
998  }
999 
1000  if (!system->bypassCaches()) {
1001  // forward to all snoopers but the source
1002  forwardFunctional(pkt, slave_port_id);
1003  }
1004 
1005  // there is no need to continue if the snooping has found what we
1006  // were looking for and the packet is already a response
1007  if (!pkt->isResponse()) {
1008  // since our slave ports are queued ports we need to check them as well
1009  for (const auto& p : slavePorts) {
1010  // if we find a response that has the data, then the
1011  // downstream caches/memories may be out of date, so simply stop
1012  // here
1013  if (p->trySatisfyFunctional(pkt)) {
1014  if (pkt->needsResponse())
1015  pkt->makeResponse();
1016  return;
1017  }
1018  }
1019 
1020  PortID dest_id = findPort(pkt->getAddrRange());
1021 
1022  masterPorts[dest_id]->sendFunctional(pkt);
1023  }
1024 }
1025 
1026 void
1028 {
1029  if (!pkt->isPrint()) {
1030  // don't do DPRINTFs on PrintReq as it clutters up the output
1031  DPRINTF(CoherentXBar, "%s: src %s packet %s\n", __func__,
1032  masterPorts[master_port_id]->name(), pkt->print());
1033  }
1034 
1035  for (const auto& p : slavePorts) {
1036  if (p->trySatisfyFunctional(pkt)) {
1037  if (pkt->needsResponse())
1038  pkt->makeResponse();
1039  return;
1040  }
1041  }
1042 
1043  // forward to all snoopers
1045 }
1046 
1047 void
1049 {
1050  // snoops should only happen if the system isn't bypassing caches
1051  assert(!system->bypassCaches());
1052 
1053  for (const auto& p: snoopPorts) {
1054  // we could have gotten this request from a snooping master
1055  // (corresponding to our own slave port that is also in
1056  // snoopPorts) and should not send it back to where it came
1057  // from
1058  if (exclude_slave_port_id == InvalidPortID ||
1059  p->getId() != exclude_slave_port_id)
1060  p->sendFunctionalSnoop(pkt);
1061 
1062  // if we get a response we are done
1063  if (pkt->isResponse()) {
1064  break;
1065  }
1066  }
1067 }
1068 
1069 bool
1071 {
1072  // we can sink the packet if:
1073  // 1) the crossbar is the point of coherency, and a cache is
1074  // responding after being snooped
1075  // 2) the crossbar is the point of coherency, and the packet is a
1076  // coherency packet (not a read or a write) that does not
1077  // require a response
1078  // 3) this is a clean evict or clean writeback, but the packet is
1079  // found in a cache above this crossbar
1080  // 4) a cache is responding after being snooped, and the packet
1081  // either does not need the block to be writable, or the cache
1082  // that has promised to respond (setting the cache responding
1083  // flag) is providing writable and thus had a Modified block,
1084  // and no further action is needed
1085  return (pointOfCoherency && pkt->cacheResponding()) ||
1086  (pointOfCoherency && !(pkt->isRead() || pkt->isWrite()) &&
1087  !pkt->needsResponse()) ||
1088  (pkt->isCleanEviction() && pkt->isBlockCached()) ||
1089  (pkt->cacheResponding() &&
1090  (!pkt->needsWritable() || pkt->responderHadWritable()));
1091 }
1092 
1093 bool
1095 {
1096  // we are forwarding the packet if:
1097  // 1) this is a cache clean request to the PoU/PoC and this
1098  // crossbar is above the PoU/PoC
1099  // 2) this is a read or a write
1100  // 3) this crossbar is above the point of coherency
1101  if (pkt->isClean()) {
1102  return !isDestination(pkt);
1103  }
1104  return pkt->isRead() || pkt->isWrite() || !pointOfCoherency;
1105 }
1106 
1107 
1108 void
1110 {
1112 
1113  snoopFanout.init(0, snoopPorts.size(), 1);
1114 }
1115 
1116 CoherentXBar *
1117 CoherentXBarParams::create()
1118 {
1119  return new CoherentXBar(this);
1120 }
A MasterPort is a specialisation of a BaseMasterPort, which implements the default protocol for the t...
Definition: port.hh:75
#define DPRINTF(x,...)
Definition: trace.hh:229
virtual ~CoherentXBar()
std::vector< SnoopRespLayer * > snoopLayers
void updateSnoopForward(const Packet *cpkt, const SlavePort &rsp_port, const MasterPort &req_port)
Pass snoop responses that travel downward through the snoop filter and let them update the snoop filt...
const PacketId id
Definition: packet.hh:324
bool isExpressSnoop() const
Definition: packet.hh:634
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
Definition: packet.hh:76
std::vector< RespLayer * > respLayers
Bitfield< 7 > i
const PortID InvalidPortID
Definition: types.hh:238
STL pair class.
Definition: stl.hh:61
void finishRequest(bool will_retry, Addr addr, bool is_secure)
For an un-successful request, revert the change to the snoop filter.
uint32_t snoopDelay
Keep track of the extra delay incurred by snooping upwards before sending a request down the memory s...
Definition: packet.hh:374
const unsigned int maxOutstandingSnoopCheck
Maximum number of outstading snoops sanity check.
bool isCleanEviction() const
Is this packet a clean eviction, including both actual clean evict packets, but also clean writebacks...
Definition: packet.hh:1300
std::unique_ptr< Packet > pendingDelete
Upstream caches need this packet until true is returned, so hold it for deletion until a subsequent c...
PortID defaultPortID
Port that handles requests that don&#39;t match any of the interfaces.
Definition: xbar.hh:382
ip6_addr_t addr
Definition: inet.hh:335
bool isClean() const
Definition: packet.hh:545
void setSlavePorts(const SnoopList &slave_ports)
Init a new snoop filter and tell it about all the slave ports of the enclosing bus.
void recvReqRetry(PortID master_port_id)
Stats::Distribution snoopFanout
std::unordered_map< RequestPtr, PortID > routeTo
Remember where request packets came from so that we can route responses to the appropriate port...
Definition: xbar.hh:326
bool cacheResponding() const
Definition: packet.hh:591
Internal class to bridge between an incoming snoop response from a slave port and forwarding it throu...
const Cycles responseLatency
Definition: xbar.hh:314
A queued port is a port that has an infinite queue for outgoing packets and thus decouples the module...
Definition: qport.hh:60
A SlavePort is a specialisation of a port.
Definition: port.hh:258
std::vector< ReqLayer * > reqLayers
Declare the layers of this crossbar, one vector for requests, one for responses, and one for snoop re...
Stats::Scalar snoopTraffic
const Cycles snoopResponseLatency
Cycles of snoop response latency.
System * system
Keep a pointer to the system to be allow to querying memory system properties.
Tick clockPeriod() const
bool isWrite() const
Definition: packet.hh:529
Declaration of the coherent crossbar slave port type, one will be instantiated for each of the master...
std::unordered_set< RequestPtr > outstandingSnoop
Store the outstanding requests that we are expecting snoop responses from so we can determine which s...
bool isRead() const
Definition: packet.hh:528
bool sinkPacket(const PacketPtr pkt) const
Determine if the crossbar should sink the packet, as opposed to forwarding it, or responding...
void recvFunctionalSnoop(PacketPtr pkt, PortID master_port_id)
Function called by the port when the crossbar is recieving a functional snoop transaction.
bool recvTimingReq(PacketPtr pkt, PortID slave_port_id)
bool needsWritable() const
Definition: packet.hh:533
The base crossbar contains the common elements of the non-coherent and coherent crossbar.
Definition: xbar.hh:73
std::pair< SnoopList, Cycles > lookupSnoop(const Packet *cpkt)
Handle an incoming snoop from below (the master port).
RequestPtr req
A pointer to the original request.
Definition: packet.hh:327
void regStats() override
Callback to set stat parameters.
Definition: xbar.cc:540
bool isBlockCached() const
Definition: packet.hh:692
unsigned getSize() const
Definition: packet.hh:736
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: sim_object.cc:76
Tick curTick()
The current simulated tick.
Definition: core.hh:47
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:162
bool needsResponse() const
Definition: packet.hh:542
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition: packet.hh:366
uint64_t Tick
Tick count type.
Definition: types.hh:63
Stats::Vector transDist
Stats for transaction distribution and data passing through the crossbar.
Definition: xbar.hh:401
bool isResponse() const
Definition: packet.hh:532
bool isDestination(const PacketPtr pkt) const
Determine if the packet&#39;s destination is the memory below.
void recvTimingSnoopReq(PacketPtr pkt, PortID master_port_id)
const unsigned int maxRoutingTableSizeCheck
Maximum routing table size sanity check.
CoherentXBar(const CoherentXBarParams *p)
SnoopFilter * snoopFilter
A snoop filter that tracks cache line residency and can restrict the broadcast needed for probes...
Addr getAddr() const
Definition: packet.hh:726
AddrRange getAddrRange() const
Get address range to which this packet belongs.
Definition: packet.cc:228
bool hasData() const
Definition: packet.hh:548
void calcPacketTiming(PacketPtr pkt, Tick header_delay)
Calculate the timing parameters for the packet.
Definition: xbar.cc:103
Distribution & init(Counter min, Counter max, Counter bkt)
Set the parameters of this distribution.
Definition: statistics.hh:2609
bool recvTimingResp(PacketPtr pkt, PortID master_port_id)
void forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id)
Forward a timing packet to our snoopers, potentially excluding one of the connected coherent masters ...
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
Definition: packet.hh:384
virtual const std::string name() const
Definition: sim_object.hh:120
A coherent crossbar connects a number of (potentially) snooping masters and slaves, and routes the request and response packets based on the address, and also forwards all requests to the snoopers and deals with the snoop responses.
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:255
const Cycles frontendLatency
Cycles of front-end pipeline including the delay to accept the request and to decode the address...
Definition: xbar.hh:312
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
void updateResponse(const Packet *cpkt, const SlavePort &slave_port)
Update the snoop filter with a response from below (outer / other cache, or memory) and update the tr...
bool responderHadWritable() const
Definition: packet.hh:651
Bitfield< 15 > system
Definition: misc.hh:999
Declaration of a coherent crossbar.
Tick recvAtomicSnoop(PacketPtr pkt, PortID master_port_id)
int cmdToIndex() const
Return the index of this command.
Definition: packet.hh:526
bool satisfied() const
Definition: packet.hh:687
std::vector< MasterPort * > masterPorts
Definition: xbar.hh:379
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
Definition: packet.hh:937
std::vector< SnoopRespPort * > snoopRespPorts
Stats::Scalar snoops
std::vector< QueuedSlavePort * > slavePorts
The master and slave ports of the crossbar.
Definition: xbar.hh:378
void print(std::ostream &o, int verbosity=0, const std::string &prefix="") const
Definition: packet.cc:376
MemCmd cmd
The command field of the packet.
Definition: packet.hh:322
bool bypassCaches() const
Should caches be bypassed?
Definition: system.hh:160
bool isEviction() const
Definition: packet.hh:544
const std::string name() const
Return port name (for DPRINTF).
Definition: port.hh:106
PortID findPort(AddrRange addr_range)
Find which port connected to this crossbar (if any) should be given a packet with this address range...
Definition: xbar.cc:329
void forwardFunctional(PacketPtr pkt, PortID exclude_slave_port_id)
Forward a functional packet to our snoopers, potentially excluding one of the connected coherent mast...
bool isPrint() const
Definition: packet.hh:556
std::pair< MemCmd, Tick > forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id)
Forward an atomic packet to our snoopers, potentially excluding one of the connected coherent masters...
void setBlockCached()
Definition: packet.hh:691
bool isSecure() const
Definition: packet.hh:755
virtual void regStats()
Callback to set stat parameters.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:237
const Cycles forwardLatency
Definition: xbar.hh:313
#define warn(...)
Definition: logging.hh:212
void setExpressSnoop()
The express snoop flag is used for two purposes.
Definition: packet.hh:633
bool forwardPacket(const PacketPtr pkt)
Determine if the crossbar should forward the packet, as opposed to responding to it.
const bool pointOfCoherency
Is this crossbar the point of coherency?
void updateSnoopResponse(const Packet *cpkt, const SlavePort &rsp_port, const SlavePort &req_port)
Let the snoop filter see any snoop responses that turn into request responses and indicate cache to c...
static const int NumArgumentRegs M5_VAR_USED
Definition: process.cc:84
bool recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
Bitfield< 0 > p
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:185
Stats::Vector2d pktSize
Definition: xbar.hh:403
Bitfield< 5 > l
std::unordered_map< PacketId, PacketPtr > outstandingCMO
Store the outstanding cache maintenance that we are expecting snoop responses from so we can determin...
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Definition: statistics.hh:1899
std::pair< SnoopList, Cycles > lookupRequest(const Packet *cpkt, const SlavePort &slave_port)
Lookup a request (from a slave port) in the snoop filter and return a list of other slave ports that ...
Definition: snoop_filter.cc:66
Declaration of the coherent crossbar master port type, one will be instantiated for each of the slave...
Tick recvAtomicBackdoor(PacketPtr pkt, PortID slave_port_id, MemBackdoorPtr *backdoor=nullptr)
void recvFunctional(PacketPtr pkt, PortID slave_port_id)
Function called by the port when the crossbar is recieving a Functional transaction.
Stats::Vector2d pktCount
Definition: xbar.hh:402
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
std::vector< QueuedSlavePort * > snoopPorts
void clearWriteThrough()
Definition: packet.hh:673

Generated on Fri Feb 28 2020 16:27:02 for gem5 by doxygen 1.8.13