X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmem%2Fbus.cc;h=d29422593214fd3971b8a5c6410988c1afa0a459;hb=8573a69d8f7bf7b3f074e3e0ac64994801c551be;hp=4d9cdbe885ed2b120d72be10e8f56b09faed5310;hpb=7cd49b24d2523eaf21179946e291c46c6acf5bfc;p=gem5.git diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 4d9cdbe88..d29422593 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -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 @@ -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 intlv_ranges; + for (AddrRangeMap::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