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

Generated on Tue Sep 21 2021 12:25:30 for gem5 by doxygen 1.8.17