ruby: move stall and wakeup functions to AbstractController
[gem5.git] / src / mem / bus.cc
index 4d9cdbe885ed2b120d72be10e8f56b09faed5310..d29422593214fd3971b8a5c6410988c1afa0a459 100644 (file)
@@ -129,30 +129,31 @@ BaseBus::getSlavePort(const std::string &if_name, PortID idx)
     }
 }
 
-Tick
+void
 BaseBus::calcPacketTiming(PacketPtr pkt)
 {
-    // determine the header time rounded to the closest following
-    // clock edge
-    Tick headerTime = clockEdge(headerCycles);
-
-    // The packet will be sent. Figure out how long it occupies the bus, and
-    // how much of that time is for the first "word", aka bus width.
-    Cycles numCycles(0);
-    if (pkt->hasData()) {
-        // If a packet has data, it needs ceil(size/width) cycles to send it
-        unsigned dataSize = pkt->getSize();
-        numCycles = Cycles(divCeil(dataSize, width));
-    }
+    // the bus will be called at a time that is not necessarily
+    // coinciding with its own clock, so start by determining how long
+    // until the next clock edge (could be zero)
+    Tick offset = nextCycle() - curTick();
 
-    // The first word will be delivered on the cycle after the header.
-    pkt->firstWordTime = headerTime + clockPeriod();
+    // determine how many cycles are needed to send the data
+    unsigned dataCycles = pkt->hasData() ? divCeil(pkt->getSize(), width) : 0;
 
-    // Note that currently finishTime can be smaller than
-    // firstWordTime if the packet has no data
-    pkt->finishTime = headerTime + numCycles * clockPeriod();
+    // before setting the bus delay fields of the packet, ensure that
+    // the delay from any previous bus has been accounted for
+    if (pkt->busFirstWordDelay != 0 || pkt->busLastWordDelay != 0)
+        panic("Packet %s already has bus delay (%d, %d) that should be "
+              "accounted for.\n", pkt->cmdString(), pkt->busFirstWordDelay,
+              pkt->busLastWordDelay);
 
-    return headerTime;
+    // The first word will be delivered on the cycle after the header.
+    pkt->busFirstWordDelay = (headerCycles + 1) * clockPeriod() + offset;
+
+    // Note that currently busLastWordDelay can be smaller than
+    // busFirstWordDelay if the packet has no data
+    pkt->busLastWordDelay = (headerCycles + dataCycles) * clockPeriod() +
+        offset;
 }
 
 template <typename PortClass>
@@ -441,31 +442,83 @@ BaseBus::recvRangeChange(PortID master_port_id)
     // modules, go ahead and tell our connected master modules in
     // turn, this effectively assumes a tree structure of the system
     if (gotAllAddrRanges) {
+        DPRINTF(BusAddrRanges, "Aggregating bus ranges\n");
+        busRanges.clear();
+
+        // start out with the default range
+        if (useDefaultRange) {
+            if (!gotAddrRanges[defaultPortID])
+                fatal("Bus %s uses default range, but none provided",
+                      name());
+
+            busRanges.push_back(defaultRange);
+            DPRINTF(BusAddrRanges, "-- Adding default %s\n",
+                    defaultRange.to_string());
+        }
+
+        // merge all interleaved ranges and add any range that is not
+        // a subset of the default range
+        std::vector<AddrRange> intlv_ranges;
+        for (AddrRangeMap<PortID>::const_iterator r = portMap.begin();
+             r != portMap.end(); ++r) {
+            // if the range is interleaved then save it for now
+            if (r->first.interleaved()) {
+                // if we already got interleaved ranges that are not
+                // part of the same range, then first do a merge
+                // before we add the new one
+                if (!intlv_ranges.empty() &&
+                    !intlv_ranges.back().mergesWith(r->first)) {
+                    DPRINTF(BusAddrRanges, "-- Merging range from %d ranges\n",
+                            intlv_ranges.size());
+                    AddrRange merged_range(intlv_ranges);
+                    // next decide if we keep the merged range or not
+                    if (!(useDefaultRange &&
+                          merged_range.isSubset(defaultRange))) {
+                        busRanges.push_back(merged_range);
+                        DPRINTF(BusAddrRanges, "-- Adding merged range %s\n",
+                                merged_range.to_string());
+                    }
+                    intlv_ranges.clear();
+                }
+                intlv_ranges.push_back(r->first);
+            } else {
+                // keep the current range if not a subset of the default
+                if (!(useDefaultRange &&
+                      r->first.isSubset(defaultRange))) {
+                    busRanges.push_back(r->first);
+                    DPRINTF(BusAddrRanges, "-- Adding range %s\n",
+                            r->first.to_string());
+                }
+            }
+        }
+
+        // if there is still interleaved ranges waiting to be merged,
+        // go ahead and do it
+        if (!intlv_ranges.empty()) {
+            DPRINTF(BusAddrRanges, "-- Merging range from %d ranges\n",
+                    intlv_ranges.size());
+            AddrRange merged_range(intlv_ranges);
+            if (!(useDefaultRange && merged_range.isSubset(defaultRange))) {
+                busRanges.push_back(merged_range);
+                DPRINTF(BusAddrRanges, "-- Adding merged range %s\n",
+                        merged_range.to_string());
+            }
+        }
+
         // also check that no range partially overlaps with the
         // default range, this has to be done after all ranges are set
         // as there are no guarantees for when the default range is
         // update with respect to the other ones
         if (useDefaultRange) {
-            for (PortID port_id = 0; port_id < masterPorts.size(); ++port_id) {
-                if (port_id == defaultPortID) {
-                    if (!gotAddrRanges[port_id])
-                        fatal("Bus %s uses default range, but none provided",
-                              name());
-                } else {
-                    AddrRangeList ranges =
-                        masterPorts[port_id]->getAddrRanges();
-
-                    for (AddrRangeConstIter r = ranges.begin();
-                         r != ranges.end(); ++r) {
-                        // see if the new range is partially
-                        // overlapping the default range
-                        if (r->intersects(defaultRange) &&
-                            !r->isSubset(defaultRange))
-                            fatal("Range %s intersects the " \
-                                  "default range of %s but is not a " \
-                                  "subset\n", r->to_string(), name());
-                    }
-                }
+            for (AddrRangeConstIter r = busRanges.begin();
+                 r != busRanges.end(); ++r) {
+                // see if the new range is partially
+                // overlapping the default range
+                if (r->intersects(defaultRange) &&
+                    !r->isSubset(defaultRange))
+                    fatal("Range %s intersects the "                    \
+                          "default range of %s but is not a "           \
+                          "subset\n", r->to_string(), name());
             }
         }
 
@@ -492,27 +545,9 @@ BaseBus::getAddrRanges() const
     // (CPU, cache, bridge etc) actually care about the ranges of the
     // ports they are connected to
 
-    DPRINTF(BusAddrRanges, "Received address range request, returning:\n");
-
-    // start out with the default range
-    AddrRangeList ranges;
-    if (useDefaultRange) {
-        ranges.push_back(defaultRange);
-        DPRINTF(BusAddrRanges, "  -- Default %s\n", defaultRange.to_string());
-    }
-
-    // add any range that is not a subset of the default range
-    for (PortMapConstIter p = portMap.begin(); p != portMap.end(); ++p) {
-        if (useDefaultRange && p->first.isSubset(defaultRange)) {
-            DPRINTF(BusAddrRanges, "  -- %s is a subset of default\n",
-                    p->first.to_string());
-        } else {
-            ranges.push_back(p->first);
-            DPRINTF(BusAddrRanges, "  -- %s\n", p->first.to_string());
-        }
-    }
+    DPRINTF(BusAddrRanges, "Received address range request\n");
 
-    return ranges;
+    return busRanges;
 }
 
 unsigned