gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
xbar.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2015, 2018-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  */
44 
50 #include "mem/xbar.hh"
51 
52 #include "base/logging.hh"
53 #include "base/trace.hh"
54 #include "debug/AddrRanges.hh"
55 #include "debug/Drain.hh"
56 #include "debug/XBar.hh"
57 
58 BaseXBar::BaseXBar(const BaseXBarParams *p)
59  : ClockedObject(p),
60  frontendLatency(p->frontend_latency),
61  forwardLatency(p->forward_latency),
62  responseLatency(p->response_latency),
63  width(p->width),
64  gotAddrRanges(p->port_default_connection_count +
65  p->port_master_connection_count, false),
66  gotAllAddrRanges(false), defaultPortID(InvalidPortID),
67  useDefaultRange(p->use_default_range),
68 
69  transDist(this, "trans_dist", "Transaction distribution"),
70  pktCount(this, "pkt_count",
71  "Packet count per connected master and slave (bytes)"),
72  pktSize(this, "pkt_size",
73  "Cumulative packet size per connected master and slave (bytes)")
74 {
75 }
76 
78 {
79  for (auto m: masterPorts)
80  delete m;
81 
82  for (auto s: slavePorts)
83  delete s;
84 }
85 
86 Port &
87 BaseXBar::getPort(const std::string &if_name, PortID idx)
88 {
89  if (if_name == "master" && idx < masterPorts.size()) {
90  // the master port index translates directly to the vector position
91  return *masterPorts[idx];
92  } else if (if_name == "default") {
93  return *masterPorts[defaultPortID];
94  } else if (if_name == "slave" && idx < slavePorts.size()) {
95  // the slave port index translates directly to the vector position
96  return *slavePorts[idx];
97  } else {
98  return ClockedObject::getPort(if_name, idx);
99  }
100 }
101 
102 void
104 {
105  // the crossbar will be called at a time that is not necessarily
106  // coinciding with its own clock, so start by determining how long
107  // until the next clock edge (could be zero)
108  Tick offset = clockEdge() - curTick();
109 
110  // the header delay depends on the path through the crossbar, and
111  // we therefore rely on the caller to provide the actual
112  // value
113  pkt->headerDelay += offset + header_delay;
114 
115  // note that we add the header delay to the existing value, and
116  // align it to the crossbar clock
117 
118  // do a quick sanity check to ensure the timings are not being
119  // ignored, note that this specific value may cause problems for
120  // slower interconnects
122  "Encountered header delay exceeding 1 us\n");
123 
124  if (pkt->hasData()) {
125  // the payloadDelay takes into account the relative time to
126  // deliver the payload of the packet, after the header delay,
127  // we take the maximum since the payload delay could already
128  // be longer than what this parcitular crossbar enforces.
129  pkt->payloadDelay = std::max<Tick>(pkt->payloadDelay,
130  divCeil(pkt->getSize(), width) *
131  clockPeriod());
132  }
133 
134  // the payload delay is not paying for the clock offset as that is
135  // already done using the header delay, and the payload delay is
136  // also used to determine how long the crossbar layer is busy and
137  // thus regulates throughput
138 }
139 
140 template <typename SrcType, typename DstType>
142  const std::string& _name) :
143  Stats::Group(&_xbar, _name.c_str()),
144  port(_port), xbar(_xbar), _name(xbar.name() + "." + _name), state(IDLE),
145  waitingForPeer(NULL), releaseEvent([this]{ releaseLayer(); }, name()),
146  ADD_STAT(occupancy, "Layer occupancy (ticks)"),
147  ADD_STAT(utilization, "Layer utilization (%)")
148 {
149  occupancy
150  .flags(Stats::nozero);
151 
152  utilization
153  .precision(1)
154  .flags(Stats::nozero);
155 
156  utilization = 100 * occupancy / simTicks;
157 }
158 
159 template <typename SrcType, typename DstType>
161 {
162  // ensure the state is busy at this point, as the layer should
163  // transition from idle as soon as it has decided to forward the
164  // packet to prevent any follow-on calls to sendTiming seeing an
165  // unoccupied layer
166  assert(state == BUSY);
167 
168  // until should never be 0 as express snoops never occupy the layer
169  assert(until != 0);
170  xbar.schedule(releaseEvent, until);
171 
172  // account for the occupied ticks
173  occupancy += until - curTick();
174 
175  DPRINTF(BaseXBar, "The crossbar layer is now busy from tick %d to %d\n",
176  curTick(), until);
177 }
178 
179 template <typename SrcType, typename DstType>
180 bool
182 {
183  // if we are in the retry state, we will not see anything but the
184  // retrying port (or in the case of the snoop ports the snoop
185  // response port that mirrors the actual slave port) as we leave
186  // this state again in zero time if the peer does not immediately
187  // call the layer when receiving the retry
188 
189  // first we see if the layer is busy, next we check if the
190  // destination port is already engaged in a transaction waiting
191  // for a retry from the peer
192  if (state == BUSY || waitingForPeer != NULL) {
193  // the port should not be waiting already
194  assert(std::find(waitingForLayer.begin(), waitingForLayer.end(),
195  src_port) == waitingForLayer.end());
196 
197  // put the port at the end of the retry list waiting for the
198  // layer to be freed up (and in the case of a busy peer, for
199  // that transaction to go through, and then the layer to free
200  // up)
201  waitingForLayer.push_back(src_port);
202  return false;
203  }
204 
205  state = BUSY;
206 
207  return true;
208 }
209 
210 template <typename SrcType, typename DstType>
211 void
213 {
214  // we should have gone from idle or retry to busy in the tryTiming
215  // test
216  assert(state == BUSY);
217 
218  // occupy the layer accordingly
219  occupyLayer(busy_time);
220 }
221 
222 template <typename SrcType, typename DstType>
223 void
225  Tick busy_time)
226 {
227  // ensure no one got in between and tried to send something to
228  // this port
229  assert(waitingForPeer == NULL);
230 
231  // if the source port is the current retrying one or not, we have
232  // failed in forwarding and should track that we are now waiting
233  // for the peer to send a retry
234  waitingForPeer = src_port;
235 
236  // we should have gone from idle or retry to busy in the tryTiming
237  // test
238  assert(state == BUSY);
239 
240  // occupy the bus accordingly
241  occupyLayer(busy_time);
242 }
243 
244 template <typename SrcType, typename DstType>
245 void
247 {
248  // releasing the bus means we should now be idle
249  assert(state == BUSY);
250  assert(!releaseEvent.scheduled());
251 
252  // update the state
253  state = IDLE;
254 
255  // bus layer is now idle, so if someone is waiting we can retry
256  if (!waitingForLayer.empty()) {
257  // there is no point in sending a retry if someone is still
258  // waiting for the peer
259  if (waitingForPeer == NULL)
260  retryWaiting();
261  } else if (waitingForPeer == NULL && drainState() == DrainState::Draining) {
262  DPRINTF(Drain, "Crossbar done draining, signaling drain manager\n");
263  //If we weren't able to drain before, do it now.
264  signalDrainDone();
265  }
266 }
267 
268 template <typename SrcType, typename DstType>
269 void
271 {
272  // this should never be called with no one waiting
273  assert(!waitingForLayer.empty());
274 
275  // we always go to retrying from idle
276  assert(state == IDLE);
277 
278  // update the state
279  state = RETRY;
280 
281  // set the retrying port to the front of the retry list and pop it
282  // off the list
283  SrcType* retryingPort = waitingForLayer.front();
284  waitingForLayer.pop_front();
285 
286  // tell the port to retry, which in some cases ends up calling the
287  // layer again
288  sendRetry(retryingPort);
289 
290  // If the layer is still in the retry state, sendTiming wasn't
291  // called in zero time (e.g. the cache does this when a writeback
292  // is squashed)
293  if (state == RETRY) {
294  // update the state to busy and reset the retrying port, we
295  // have done our bit and sent the retry
296  state = BUSY;
297 
298  // occupy the crossbar layer until the next clock edge
299  occupyLayer(xbar.clockEdge());
300  }
301 }
302 
303 template <typename SrcType, typename DstType>
304 void
306 {
307  // we should never get a retry without having failed to forward
308  // something to this port
309  assert(waitingForPeer != NULL);
310 
311  // add the port where the failed packet originated to the front of
312  // the waiting ports for the layer, this allows us to call retry
313  // on the port immediately if the crossbar layer is idle
314  waitingForLayer.push_front(waitingForPeer);
315 
316  // we are no longer waiting for the peer
317  waitingForPeer = NULL;
318 
319  // if the layer is idle, retry this port straight away, if we
320  // are busy, then simply let the port wait for its turn
321  if (state == IDLE) {
322  retryWaiting();
323  } else {
324  assert(state == BUSY);
325  }
326 }
327 
328 PortID
330 {
331  // we should never see any address lookups before we've got the
332  // ranges of all connected slave modules
333  assert(gotAllAddrRanges);
334 
335  // Check the address map interval tree
336  auto i = portMap.contains(addr_range);
337  if (i != portMap.end()) {
338  return i->second;
339  }
340 
341  // Check if this matches the default range
342  if (useDefaultRange) {
343  if (addr_range.isSubset(defaultRange)) {
344  DPRINTF(AddrRanges, " found addr %s on default\n",
345  addr_range.to_string());
346  return defaultPortID;
347  }
348  } else if (defaultPortID != InvalidPortID) {
349  DPRINTF(AddrRanges, "Unable to find destination for %s, "
350  "will use default port\n", addr_range.to_string());
351  return defaultPortID;
352  }
353 
354  // we should use the range for the default port and it did not
355  // match, or the default port is not set
356  fatal("Unable to find destination for %s on %s\n", addr_range.to_string(),
357  name());
358 }
359 
361 void
363 {
364  DPRINTF(AddrRanges, "Received range change from slave port %s\n",
365  masterPorts[master_port_id]->getPeer());
366 
367  // remember that we got a range from this master port and thus the
368  // connected slave module
369  gotAddrRanges[master_port_id] = true;
370 
371  // update the global flag
372  if (!gotAllAddrRanges) {
373  // take a logical AND of all the ports and see if we got
374  // ranges from everyone
375  gotAllAddrRanges = true;
376  std::vector<bool>::const_iterator r = gotAddrRanges.begin();
377  while (gotAllAddrRanges && r != gotAddrRanges.end()) {
378  gotAllAddrRanges &= *r++;
379  }
380  if (gotAllAddrRanges)
381  DPRINTF(AddrRanges, "Got address ranges from all slaves\n");
382  }
383 
384  // note that we could get the range from the default port at any
385  // point in time, and we cannot assume that the default range is
386  // set before the other ones are, so we do additional checks once
387  // all ranges are provided
388  if (master_port_id == defaultPortID) {
389  // only update if we are indeed checking ranges for the
390  // default port since the port might not have a valid range
391  // otherwise
392  if (useDefaultRange) {
393  AddrRangeList ranges = masterPorts[master_port_id]->getAddrRanges();
394 
395  if (ranges.size() != 1)
396  fatal("Crossbar %s may only have a single default range",
397  name());
398 
399  defaultRange = ranges.front();
400  }
401  } else {
402  // the ports are allowed to update their address ranges
403  // dynamically, so remove any existing entries
404  if (gotAddrRanges[master_port_id]) {
405  for (auto p = portMap.begin(); p != portMap.end(); ) {
406  if (p->second == master_port_id)
407  // erasing invalidates the iterator, so advance it
408  // before the deletion takes place
409  portMap.erase(p++);
410  else
411  p++;
412  }
413  }
414 
415  AddrRangeList ranges = masterPorts[master_port_id]->getAddrRanges();
416 
417  for (const auto& r: ranges) {
418  DPRINTF(AddrRanges, "Adding range %s for id %d\n",
419  r.to_string(), master_port_id);
420  if (portMap.insert(r, master_port_id) == portMap.end()) {
421  PortID conflict_id = portMap.intersects(r)->second;
422  fatal("%s has two ports responding within range "
423  "%s:\n\t%s\n\t%s\n",
424  name(),
425  r.to_string(),
426  masterPorts[master_port_id]->getPeer(),
427  masterPorts[conflict_id]->getPeer());
428  }
429  }
430  }
431 
432  // if we have received ranges from all our neighbouring slave
433  // modules, go ahead and tell our connected master modules in
434  // turn, this effectively assumes a tree structure of the system
435  if (gotAllAddrRanges) {
436  DPRINTF(AddrRanges, "Aggregating address ranges\n");
437  xbarRanges.clear();
438 
439  // start out with the default range
440  if (useDefaultRange) {
441  if (!gotAddrRanges[defaultPortID])
442  fatal("Crossbar %s uses default range, but none provided",
443  name());
444 
445  xbarRanges.push_back(defaultRange);
446  DPRINTF(AddrRanges, "-- Adding default %s\n",
447  defaultRange.to_string());
448  }
449 
450  // merge all interleaved ranges and add any range that is not
451  // a subset of the default range
452  std::vector<AddrRange> intlv_ranges;
453  for (const auto& r: portMap) {
454  // if the range is interleaved then save it for now
455  if (r.first.interleaved()) {
456  // if we already got interleaved ranges that are not
457  // part of the same range, then first do a merge
458  // before we add the new one
459  if (!intlv_ranges.empty() &&
460  !intlv_ranges.back().mergesWith(r.first)) {
461  DPRINTF(AddrRanges, "-- Merging range from %d ranges\n",
462  intlv_ranges.size());
463  AddrRange merged_range(intlv_ranges);
464  // next decide if we keep the merged range or not
465  if (!(useDefaultRange &&
466  merged_range.isSubset(defaultRange))) {
467  xbarRanges.push_back(merged_range);
468  DPRINTF(AddrRanges, "-- Adding merged range %s\n",
469  merged_range.to_string());
470  }
471  intlv_ranges.clear();
472  }
473  intlv_ranges.push_back(r.first);
474  } else {
475  // keep the current range if not a subset of the default
476  if (!(useDefaultRange &&
477  r.first.isSubset(defaultRange))) {
478  xbarRanges.push_back(r.first);
479  DPRINTF(AddrRanges, "-- Adding range %s\n",
480  r.first.to_string());
481  }
482  }
483  }
484 
485  // if there is still interleaved ranges waiting to be merged,
486  // go ahead and do it
487  if (!intlv_ranges.empty()) {
488  DPRINTF(AddrRanges, "-- Merging range from %d ranges\n",
489  intlv_ranges.size());
490  AddrRange merged_range(intlv_ranges);
491  if (!(useDefaultRange && merged_range.isSubset(defaultRange))) {
492  xbarRanges.push_back(merged_range);
493  DPRINTF(AddrRanges, "-- Adding merged range %s\n",
494  merged_range.to_string());
495  }
496  }
497 
498  // also check that no range partially intersects with the
499  // default range, this has to be done after all ranges are set
500  // as there are no guarantees for when the default range is
501  // update with respect to the other ones
502  if (useDefaultRange) {
503  for (const auto& r: xbarRanges) {
504  // see if the new range is partially
505  // overlapping the default range
506  if (r.intersects(defaultRange) &&
507  !r.isSubset(defaultRange))
508  fatal("Range %s intersects the " \
509  "default range of %s but is not a " \
510  "subset\n", r.to_string(), name());
511  }
512  }
513 
514  // tell all our neighbouring master ports that our address
515  // ranges have changed
516  for (const auto& s: slavePorts)
517  s->sendRangeChange();
518  }
519 }
520 
523 {
524  // we should never be asked without first having sent a range
525  // change, and the latter is only done once we have all the ranges
526  // of the connected devices
527  assert(gotAllAddrRanges);
528 
529  // at the moment, this never happens, as there are no cycles in
530  // the range queries and no devices on the master side of a crossbar
531  // (CPU, cache, bridge etc) actually care about the ranges of the
532  // ports they are connected to
533 
534  DPRINTF(AddrRanges, "Received address range request\n");
535 
536  return xbarRanges;
537 }
538 
539 void
541 {
543 
544  using namespace Stats;
545 
546  transDist
547  .init(MemCmd::NUM_MEM_CMDS)
548  .flags(nozero);
549 
550  // get the string representation of the commands
551  for (int i = 0; i < MemCmd::NUM_MEM_CMDS; i++) {
552  MemCmd cmd(i);
553  const std::string &cstr = cmd.toString();
554  transDist.subname(i, cstr);
555  }
556 
557  pktCount
558  .init(slavePorts.size(), masterPorts.size())
559  .flags(total | nozero | nonan);
560 
561  pktSize
562  .init(slavePorts.size(), masterPorts.size())
563  .flags(total | nozero | nonan);
564 
565  // both the packet count and total size are two-dimensional
566  // vectors, indexed by slave port id and master port id, thus the
567  // neighbouring master and slave, they do not differentiate what
568  // came from the master and was forwarded to the slave (requests
569  // and snoop responses) and what came from the slave and was
570  // forwarded to the master (responses and snoop requests)
571  for (int i = 0; i < slavePorts.size(); i++) {
572  pktCount.subname(i, slavePorts[i]->getPeer().name());
573  pktSize.subname(i, slavePorts[i]->getPeer().name());
574  for (int j = 0; j < masterPorts.size(); j++) {
575  pktCount.ysubname(j, masterPorts[j]->getPeer().name());
576  pktSize.ysubname(j, masterPorts[j]->getPeer().name());
577  }
578  }
579 }
580 
581 template <typename SrcType, typename DstType>
584 {
585  //We should check that we're not "doing" anything, and that noone is
586  //waiting. We might be idle but have someone waiting if the device we
587  //contacted for a retry didn't actually retry.
588  if (state != IDLE) {
589  DPRINTF(Drain, "Crossbar not drained\n");
590  return DrainState::Draining;
591  } else {
592  return DrainState::Drained;
593  }
594 }
595 
#define DPRINTF(x,...)
Definition: trace.hh:229
Ports are used to interface objects to each other.
Definition: port.hh:60
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
Definition: sim_object.cc:126
Tick us
microsecond
Definition: core.cc:67
void recvRetry()
Handle a retry from a neighbouring module.
Definition: xbar.cc:305
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:175
Definition: packet.hh:76
const std::string & name()
Definition: trace.cc:54
Bitfield< 7 > i
const PortID InvalidPortID
Definition: types.hh:238
DrainState
Object drain/handover states.
Definition: drain.hh:71
Bitfield< 0 > m
Running normally.
const FlagsType nonan
Don&#39;t print if this is NAN.
Definition: info.hh:61
const std::string & toString() const
Return the string to a cmd given by idx.
Definition: packet.hh:237
PortID defaultPortID
Port that handles requests that don&#39;t match any of the interfaces.
Definition: xbar.hh:382
bool isSubset(const AddrRange &r) const
Determine if this range is a subset of another range, i.e.
Definition: addr_range.hh:383
virtual void regStats()
Callback to set stat parameters.
Definition: group.cc:66
AddrRangeList getAddrRanges() const
Return the address ranges the crossbar is responsible for.
Definition: xbar.cc:522
Bitfield< 23, 0 > offset
Definition: types.hh:154
Tick clockPeriod() const
STL vector class.
Definition: stl.hh:40
The base crossbar contains the common elements of the non-coherent and coherent crossbar.
Definition: xbar.hh:73
void regStats() override
Callback to set stat parameters.
Definition: xbar.cc:540
void succeededTiming(Tick busy_time)
Deal with a destination port accepting a packet by potentially removing the source port from the retr...
Definition: xbar.cc:212
unsigned getSize() const
Definition: packet.hh:736
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
Definition: addr_range.hh:72
Tick curTick()
The current simulated tick.
Definition: core.hh:47
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
Definition: packet.hh:366
Bitfield< 4 > s
virtual ~BaseXBar()
Definition: xbar.cc:77
const uint32_t width
the width of the xbar in bytes
Definition: xbar.hh:316
uint64_t Tick
Tick count type.
Definition: types.hh:63
BaseXBar(const BaseXBarParams *p)
Definition: xbar.cc:58
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Group()=delete
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
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
A function used to return the port associated with this object.
Definition: xbar.cc:87
Draining buffers pending serialization/handover.
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
void failedTiming(SrcType *src_port, Tick busy_time)
Deal with a destination port not accepting a packet by potentially adding the source port to the retr...
Definition: xbar.cc:224
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:255
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...
const FlagsType total
Print the total.
Definition: info.hh:51
Bitfield< 24 > j
std::vector< MasterPort * > masterPorts
Definition: xbar.hh:379
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:69
std::vector< QueuedSlavePort * > slavePorts
The master and slave ports of the crossbar.
Definition: xbar.hh:378
void occupyLayer(Tick until)
Definition: xbar.cc:160
void releaseLayer()
Release the layer after being occupied and return to an idle state where we proceed to send a retry t...
Definition: xbar.cc:246
DrainState drain() override
Drain according to the normal semantics, so that the crossbar can tell the layer to drain...
Definition: xbar.cc:583
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
T divCeil(const T &a, const U &b)
Definition: intmath.hh:153
Layer(DstType &_port, BaseXBar &_xbar, const std::string &_name)
Create a layer and give it a name.
Definition: xbar.cc:141
Bitfield< 4 > width
bool tryTiming(SrcType *src_port)
Determine if the layer accepts a packet from a specific port.
Definition: xbar.cc:181
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:237
std::string to_string() const
Get a string representation of the range.
Definition: addr_range.hh:309
const FlagsType nozero
Don&#39;t print if this is zero.
Definition: info.hh:59
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
void retryWaiting()
Send a retry to the port at the head of waitingForLayer.
Definition: xbar.cc:270
Declaration of an abstract crossbar base class.
virtual void recvRangeChange(PortID master_port_id)
Function called by the port when the crossbar is recieving a range change.
Definition: xbar.cc:362
Stats::Value simTicks
Definition: stat_control.cc:65

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