tests: Add a memtest version using the ideal SnoopFilter
[gem5.git] / src / mem / bus.cc
1 /*
2 * Copyright (c) 2011-2013 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
45 /**
46 * @file
47 * Definition of a bus object.
48 */
49
50 #include "base/misc.hh"
51 #include "base/trace.hh"
52 #include "debug/Bus.hh"
53 #include "debug/BusAddrRanges.hh"
54 #include "debug/Drain.hh"
55 #include "mem/bus.hh"
56
57 BaseBus::BaseBus(const BaseBusParams *p)
58 : MemObject(p),
59 headerCycles(p->header_cycles), width(p->width),
60 gotAddrRanges(p->port_default_connection_count +
61 p->port_master_connection_count, false),
62 gotAllAddrRanges(false), defaultPortID(InvalidPortID),
63 useDefaultRange(p->use_default_range)
64 {}
65
66 BaseBus::~BaseBus()
67 {
68 for (MasterPortIter m = masterPorts.begin(); m != masterPorts.end();
69 ++m) {
70 delete *m;
71 }
72
73 for (SlavePortIter s = slavePorts.begin(); s != slavePorts.end();
74 ++s) {
75 delete *s;
76 }
77 }
78
79 void
80 BaseBus::init()
81 {
82 }
83
84 BaseMasterPort &
85 BaseBus::getMasterPort(const std::string &if_name, PortID idx)
86 {
87 if (if_name == "master" && idx < masterPorts.size()) {
88 // the master port index translates directly to the vector position
89 return *masterPorts[idx];
90 } else if (if_name == "default") {
91 return *masterPorts[defaultPortID];
92 } else {
93 return MemObject::getMasterPort(if_name, idx);
94 }
95 }
96
97 BaseSlavePort &
98 BaseBus::getSlavePort(const std::string &if_name, PortID idx)
99 {
100 if (if_name == "slave" && idx < slavePorts.size()) {
101 // the slave port index translates directly to the vector position
102 return *slavePorts[idx];
103 } else {
104 return MemObject::getSlavePort(if_name, idx);
105 }
106 }
107
108 void
109 BaseBus::calcPacketTiming(PacketPtr pkt)
110 {
111 // the bus will be called at a time that is not necessarily
112 // coinciding with its own clock, so start by determining how long
113 // until the next clock edge (could be zero)
114 Tick offset = clockEdge() - curTick();
115
116 // determine how many cycles are needed to send the data
117 unsigned dataCycles = pkt->hasData() ? divCeil(pkt->getSize(), width) : 0;
118
119 // before setting the bus delay fields of the packet, ensure that
120 // the delay from any previous bus has been accounted for
121 if (pkt->busFirstWordDelay != 0 || pkt->busLastWordDelay != 0)
122 panic("Packet %s already has bus delay (%d, %d) that should be "
123 "accounted for.\n", pkt->cmdString(), pkt->busFirstWordDelay,
124 pkt->busLastWordDelay);
125
126 // The first word will be delivered on the cycle after the header.
127 pkt->busFirstWordDelay = (headerCycles + 1) * clockPeriod() + offset;
128
129 // Note that currently busLastWordDelay can be smaller than
130 // busFirstWordDelay if the packet has no data
131 pkt->busLastWordDelay = (headerCycles + dataCycles) * clockPeriod() +
132 offset;
133 }
134
135 template <typename SrcType, typename DstType>
136 BaseBus::Layer<SrcType,DstType>::Layer(DstType& _port, BaseBus& _bus,
137 const std::string& _name) :
138 port(_port), bus(_bus), _name(_name), state(IDLE), drainManager(NULL),
139 waitingForPeer(NULL), releaseEvent(this)
140 {
141 }
142
143 template <typename SrcType, typename DstType>
144 void BaseBus::Layer<SrcType,DstType>::occupyLayer(Tick until)
145 {
146 // ensure the state is busy at this point, as the bus should
147 // transition from idle as soon as it has decided to forward the
148 // packet to prevent any follow-on calls to sendTiming seeing an
149 // unoccupied bus
150 assert(state == BUSY);
151
152 // until should never be 0 as express snoops never occupy the bus
153 assert(until != 0);
154 bus.schedule(releaseEvent, until);
155
156 // account for the occupied ticks
157 occupancy += until - curTick();
158
159 DPRINTF(BaseBus, "The bus is now busy from tick %d to %d\n",
160 curTick(), until);
161 }
162
163 template <typename SrcType, typename DstType>
164 bool
165 BaseBus::Layer<SrcType,DstType>::tryTiming(SrcType* src_port)
166 {
167 // if we are in the retry state, we will not see anything but the
168 // retrying port (or in the case of the snoop ports the snoop
169 // response port that mirrors the actual slave port) as we leave
170 // this state again in zero time if the peer does not immediately
171 // call the bus when receiving the retry
172
173 // first we see if the layer is busy, next we check if the
174 // destination port is already engaged in a transaction waiting
175 // for a retry from the peer
176 if (state == BUSY || waitingForPeer != NULL) {
177 // the port should not be waiting already
178 assert(std::find(waitingForLayer.begin(), waitingForLayer.end(),
179 src_port) == waitingForLayer.end());
180
181 // put the port at the end of the retry list waiting for the
182 // layer to be freed up (and in the case of a busy peer, for
183 // that transaction to go through, and then the bus to free
184 // up)
185 waitingForLayer.push_back(src_port);
186 return false;
187 }
188
189 // update the state to busy
190 state = BUSY;
191
192 return true;
193 }
194
195 template <typename SrcType, typename DstType>
196 void
197 BaseBus::Layer<SrcType,DstType>::succeededTiming(Tick busy_time)
198 {
199 // we should have gone from idle or retry to busy in the tryTiming
200 // test
201 assert(state == BUSY);
202
203 // occupy the bus accordingly
204 occupyLayer(busy_time);
205 }
206
207 template <typename SrcType, typename DstType>
208 void
209 BaseBus::Layer<SrcType,DstType>::failedTiming(SrcType* src_port,
210 Tick busy_time)
211 {
212 // ensure no one got in between and tried to send something to
213 // this port
214 assert(waitingForPeer == NULL);
215
216 // if the source port is the current retrying one or not, we have
217 // failed in forwarding and should track that we are now waiting
218 // for the peer to send a retry
219 waitingForPeer = src_port;
220
221 // we should have gone from idle or retry to busy in the tryTiming
222 // test
223 assert(state == BUSY);
224
225 // occupy the bus accordingly
226 occupyLayer(busy_time);
227 }
228
229 template <typename SrcType, typename DstType>
230 void
231 BaseBus::Layer<SrcType,DstType>::releaseLayer()
232 {
233 // releasing the bus means we should now be idle
234 assert(state == BUSY);
235 assert(!releaseEvent.scheduled());
236
237 // update the state
238 state = IDLE;
239
240 // bus layer is now idle, so if someone is waiting we can retry
241 if (!waitingForLayer.empty()) {
242 // there is no point in sending a retry if someone is still
243 // waiting for the peer
244 if (waitingForPeer == NULL)
245 retryWaiting();
246 } else if (waitingForPeer == NULL && drainManager) {
247 DPRINTF(Drain, "Bus done draining, signaling drain manager\n");
248 //If we weren't able to drain before, do it now.
249 drainManager->signalDrainDone();
250 // Clear the drain event once we're done with it.
251 drainManager = NULL;
252 }
253 }
254
255 template <typename SrcType, typename DstType>
256 void
257 BaseBus::Layer<SrcType,DstType>::retryWaiting()
258 {
259 // this should never be called with no one waiting
260 assert(!waitingForLayer.empty());
261
262 // we always go to retrying from idle
263 assert(state == IDLE);
264
265 // update the state
266 state = RETRY;
267
268 // set the retrying port to the front of the retry list and pop it
269 // off the list
270 SrcType* retryingPort = waitingForLayer.front();
271 waitingForLayer.pop_front();
272
273 // tell the port to retry, which in some cases ends up calling the
274 // bus
275 retryingPort->sendRetry();
276
277 // If the bus is still in the retry state, sendTiming wasn't
278 // called in zero time (e.g. the cache does this), burn a cycle
279 if (state == RETRY) {
280 // update the state to busy and reset the retrying port, we
281 // have done our bit and sent the retry
282 state = BUSY;
283
284 // occupy the bus layer until the next cycle ends
285 occupyLayer(bus.clockEdge(Cycles(1)));
286 }
287 }
288
289 template <typename SrcType, typename DstType>
290 void
291 BaseBus::Layer<SrcType,DstType>::recvRetry()
292 {
293 // we should never get a retry without having failed to forward
294 // something to this port
295 assert(waitingForPeer != NULL);
296
297 // add the port where the failed packet originated to the front of
298 // the waiting ports for the layer, this allows us to call retry
299 // on the port immediately if the bus layer is idle
300 waitingForLayer.push_front(waitingForPeer);
301
302 // we are no longer waiting for the peer
303 waitingForPeer = NULL;
304
305 // if the bus layer is idle, retry this port straight away, if we
306 // are busy, then simply let the port wait for its turn
307 if (state == IDLE) {
308 retryWaiting();
309 } else {
310 assert(state == BUSY);
311 }
312 }
313
314 PortID
315 BaseBus::findPort(Addr addr)
316 {
317 // we should never see any address lookups before we've got the
318 // ranges of all connected slave modules
319 assert(gotAllAddrRanges);
320
321 // Check the cache
322 PortID dest_id = checkPortCache(addr);
323 if (dest_id != InvalidPortID)
324 return dest_id;
325
326 // Check the address map interval tree
327 PortMapConstIter i = portMap.find(addr);
328 if (i != portMap.end()) {
329 dest_id = i->second;
330 updatePortCache(dest_id, i->first);
331 return dest_id;
332 }
333
334 // Check if this matches the default range
335 if (useDefaultRange) {
336 if (defaultRange.contains(addr)) {
337 DPRINTF(BusAddrRanges, " found addr %#llx on default\n",
338 addr);
339 return defaultPortID;
340 }
341 } else if (defaultPortID != InvalidPortID) {
342 DPRINTF(BusAddrRanges, "Unable to find destination for addr %#llx, "
343 "will use default port\n", addr);
344 return defaultPortID;
345 }
346
347 // we should use the range for the default port and it did not
348 // match, or the default port is not set
349 fatal("Unable to find destination for addr %#llx on bus %s\n", addr,
350 name());
351 }
352
353 /** Function called by the port when the bus is receiving a range change.*/
354 void
355 BaseBus::recvRangeChange(PortID master_port_id)
356 {
357 DPRINTF(BusAddrRanges, "Received range change from slave port %s\n",
358 masterPorts[master_port_id]->getSlavePort().name());
359
360 // remember that we got a range from this master port and thus the
361 // connected slave module
362 gotAddrRanges[master_port_id] = true;
363
364 // update the global flag
365 if (!gotAllAddrRanges) {
366 // take a logical AND of all the ports and see if we got
367 // ranges from everyone
368 gotAllAddrRanges = true;
369 std::vector<bool>::const_iterator r = gotAddrRanges.begin();
370 while (gotAllAddrRanges && r != gotAddrRanges.end()) {
371 gotAllAddrRanges &= *r++;
372 }
373 if (gotAllAddrRanges)
374 DPRINTF(BusAddrRanges, "Got address ranges from all slaves\n");
375 }
376
377 // note that we could get the range from the default port at any
378 // point in time, and we cannot assume that the default range is
379 // set before the other ones are, so we do additional checks once
380 // all ranges are provided
381 if (master_port_id == defaultPortID) {
382 // only update if we are indeed checking ranges for the
383 // default port since the port might not have a valid range
384 // otherwise
385 if (useDefaultRange) {
386 AddrRangeList ranges = masterPorts[master_port_id]->getAddrRanges();
387
388 if (ranges.size() != 1)
389 fatal("Bus %s may only have a single default range",
390 name());
391
392 defaultRange = ranges.front();
393 }
394 } else {
395 // the ports are allowed to update their address ranges
396 // dynamically, so remove any existing entries
397 if (gotAddrRanges[master_port_id]) {
398 for (PortMapIter p = portMap.begin(); p != portMap.end(); ) {
399 if (p->second == master_port_id)
400 // erasing invalidates the iterator, so advance it
401 // before the deletion takes place
402 portMap.erase(p++);
403 else
404 p++;
405 }
406 }
407
408 AddrRangeList ranges = masterPorts[master_port_id]->getAddrRanges();
409
410 for (AddrRangeConstIter r = ranges.begin(); r != ranges.end(); ++r) {
411 DPRINTF(BusAddrRanges, "Adding range %s for id %d\n",
412 r->to_string(), master_port_id);
413 if (portMap.insert(*r, master_port_id) == portMap.end()) {
414 PortID conflict_id = portMap.find(*r)->second;
415 fatal("%s has two ports with same range:\n\t%s\n\t%s\n",
416 name(),
417 masterPorts[master_port_id]->getSlavePort().name(),
418 masterPorts[conflict_id]->getSlavePort().name());
419 }
420 }
421 }
422
423 // if we have received ranges from all our neighbouring slave
424 // modules, go ahead and tell our connected master modules in
425 // turn, this effectively assumes a tree structure of the system
426 if (gotAllAddrRanges) {
427 DPRINTF(BusAddrRanges, "Aggregating bus ranges\n");
428 busRanges.clear();
429
430 // start out with the default range
431 if (useDefaultRange) {
432 if (!gotAddrRanges[defaultPortID])
433 fatal("Bus %s uses default range, but none provided",
434 name());
435
436 busRanges.push_back(defaultRange);
437 DPRINTF(BusAddrRanges, "-- Adding default %s\n",
438 defaultRange.to_string());
439 }
440
441 // merge all interleaved ranges and add any range that is not
442 // a subset of the default range
443 std::vector<AddrRange> intlv_ranges;
444 for (AddrRangeMap<PortID>::const_iterator r = portMap.begin();
445 r != portMap.end(); ++r) {
446 // if the range is interleaved then save it for now
447 if (r->first.interleaved()) {
448 // if we already got interleaved ranges that are not
449 // part of the same range, then first do a merge
450 // before we add the new one
451 if (!intlv_ranges.empty() &&
452 !intlv_ranges.back().mergesWith(r->first)) {
453 DPRINTF(BusAddrRanges, "-- Merging range from %d ranges\n",
454 intlv_ranges.size());
455 AddrRange merged_range(intlv_ranges);
456 // next decide if we keep the merged range or not
457 if (!(useDefaultRange &&
458 merged_range.isSubset(defaultRange))) {
459 busRanges.push_back(merged_range);
460 DPRINTF(BusAddrRanges, "-- Adding merged range %s\n",
461 merged_range.to_string());
462 }
463 intlv_ranges.clear();
464 }
465 intlv_ranges.push_back(r->first);
466 } else {
467 // keep the current range if not a subset of the default
468 if (!(useDefaultRange &&
469 r->first.isSubset(defaultRange))) {
470 busRanges.push_back(r->first);
471 DPRINTF(BusAddrRanges, "-- Adding range %s\n",
472 r->first.to_string());
473 }
474 }
475 }
476
477 // if there is still interleaved ranges waiting to be merged,
478 // go ahead and do it
479 if (!intlv_ranges.empty()) {
480 DPRINTF(BusAddrRanges, "-- Merging range from %d ranges\n",
481 intlv_ranges.size());
482 AddrRange merged_range(intlv_ranges);
483 if (!(useDefaultRange && merged_range.isSubset(defaultRange))) {
484 busRanges.push_back(merged_range);
485 DPRINTF(BusAddrRanges, "-- Adding merged range %s\n",
486 merged_range.to_string());
487 }
488 }
489
490 // also check that no range partially overlaps with the
491 // default range, this has to be done after all ranges are set
492 // as there are no guarantees for when the default range is
493 // update with respect to the other ones
494 if (useDefaultRange) {
495 for (AddrRangeConstIter r = busRanges.begin();
496 r != busRanges.end(); ++r) {
497 // see if the new range is partially
498 // overlapping the default range
499 if (r->intersects(defaultRange) &&
500 !r->isSubset(defaultRange))
501 fatal("Range %s intersects the " \
502 "default range of %s but is not a " \
503 "subset\n", r->to_string(), name());
504 }
505 }
506
507 // tell all our neighbouring master ports that our address
508 // ranges have changed
509 for (SlavePortConstIter s = slavePorts.begin(); s != slavePorts.end();
510 ++s)
511 (*s)->sendRangeChange();
512 }
513
514 clearPortCache();
515 }
516
517 AddrRangeList
518 BaseBus::getAddrRanges() const
519 {
520 // we should never be asked without first having sent a range
521 // change, and the latter is only done once we have all the ranges
522 // of the connected devices
523 assert(gotAllAddrRanges);
524
525 // at the moment, this never happens, as there are no cycles in
526 // the range queries and no devices on the master side of a bus
527 // (CPU, cache, bridge etc) actually care about the ranges of the
528 // ports they are connected to
529
530 DPRINTF(BusAddrRanges, "Received address range request\n");
531
532 return busRanges;
533 }
534
535 void
536 BaseBus::regStats()
537 {
538 using namespace Stats;
539
540 transDist
541 .init(MemCmd::NUM_MEM_CMDS)
542 .name(name() + ".trans_dist")
543 .desc("Transaction distribution")
544 .flags(nozero);
545
546 // get the string representation of the commands
547 for (int i = 0; i < MemCmd::NUM_MEM_CMDS; i++) {
548 MemCmd cmd(i);
549 const std::string &cstr = cmd.toString();
550 transDist.subname(i, cstr);
551 }
552
553 pktCount
554 .init(slavePorts.size(), masterPorts.size())
555 .name(name() + ".pkt_count")
556 .desc("Packet count per connected master and slave (bytes)")
557 .flags(total | nozero | nonan);
558
559 totPktSize
560 .init(slavePorts.size(), masterPorts.size())
561 .name(name() + ".tot_pkt_size")
562 .desc("Cumulative packet size per connected master and slave (bytes)")
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]->getMasterPort().name());
573 totPktSize.subname(i, slavePorts[i]->getMasterPort().name());
574 for (int j = 0; j < masterPorts.size(); j++) {
575 pktCount.ysubname(j, masterPorts[j]->getSlavePort().name());
576 totPktSize.ysubname(j, masterPorts[j]->getSlavePort().name());
577 }
578 }
579 }
580
581 template <typename SrcType, typename DstType>
582 unsigned int
583 BaseBus::Layer<SrcType,DstType>::drain(DrainManager *dm)
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, "Bus not drained\n");
590 drainManager = dm;
591 return 1;
592 }
593 return 0;
594 }
595
596 template <typename SrcType, typename DstType>
597 void
598 BaseBus::Layer<SrcType,DstType>::regStats()
599 {
600 using namespace Stats;
601
602 occupancy
603 .name(name() + ".occupancy")
604 .desc("Layer occupancy (ticks)")
605 .flags(nozero);
606
607 utilization
608 .name(name() + ".utilization")
609 .desc("Layer utilization (%)")
610 .precision(1)
611 .flags(nozero);
612
613 utilization = 100 * occupancy / simTicks;
614 }
615
616 /**
617 * Bus layer template instantiations. Could be removed with _impl.hh
618 * file, but since there are only two given options (MasterPort and
619 * SlavePort) it seems a bit excessive at this point.
620 */
621 template class BaseBus::Layer<SlavePort,MasterPort>;
622 template class BaseBus::Layer<MasterPort,SlavePort>;