src/mem/xbar.cc
/** Function called by the port when the crossbar is receiving a range change.*/
Function called by the port when the crossbar is receiving a range change.
Function called by the port when the crossbar is receiving a range change .
void
BaseXBar::recvRangeChange(PortID mem_side_port_id)
{
    DPRINTF(AddrRanges, "Received range change from cpu_side_ports %s\n",
            memSidePorts[mem_side_port_id]->getPeer());
    gotAddrRanges[mem_side_port_id] = true;
    if (!gotAllAddrRanges) {
        gotAllAddrRanges = true;
        std::vector<bool>::const_iterator r = gotAddrRanges.begin();
        while (gotAllAddrRanges &&  r != gotAddrRanges.end()) {
            gotAllAddrRanges &= *r++;
        }
        if (gotAllAddrRanges)
            DPRINTF(AddrRanges, "Got address ranges from all responders\n");
    }
    if (mem_side_port_id == defaultPortID) {
        if (useDefaultRange) {
            AddrRangeList ranges = memSidePorts[mem_side_port_id]->
                                   getAddrRanges();
            if (ranges.size() != 1)
                fatal("Crossbar %s may only have a single default range",
                      name());
            defaultRange = ranges.front();
        }
    } else {
        if (gotAddrRanges[mem_side_port_id]) {
            for (auto p = portMap.begin(); p != portMap.end(); ) {
                if (p->second == mem_side_port_id)
                    portMap.erase(p++);
                else
                    p++;
            }
        }
        AddrRangeList ranges = memSidePorts[mem_side_port_id]->
                               getAddrRanges();
        for (const auto& r: ranges) {
            DPRINTF(AddrRanges, "Adding range %s for id %d\n",
                    r.to_string(), mem_side_port_id);
            if (portMap.insert(r, mem_side_port_id) == portMap.end()) {
                PortID conflict_id = portMap.intersects(r)->second;
                fatal("%s has two ports responding within range "
                      "%s:\n\t%s\n\t%s\n",
                      name(),
                      r.to_string(),
                      memSidePorts[mem_side_port_id]->getPeer(),
                      memSidePorts[conflict_id]->getPeer());
            }
        }
    }
    if (gotAllAddrRanges) {
        DPRINTF(AddrRanges, "Aggregating address ranges\n");
        xbarRanges.clear();
        if (useDefaultRange) {
            if (!gotAddrRanges[defaultPortID])
                fatal("Crossbar %s uses default range, but none provided",
                      name());
            xbarRanges.push_back(defaultRange);
            DPRINTF(AddrRanges, "-- Adding default %s\n",
                    defaultRange.to_string());
        }
        std::vector<AddrRange> intlv_ranges;
        for (const auto& r: portMap) {
            if (r.first.interleaved()) {
                if (!intlv_ranges.empty() &&
                    !intlv_ranges.back().mergesWith(r.first)) {
                    DPRINTF(AddrRanges, "-- Merging range from %d ranges\n",
                            intlv_ranges.size());
                    AddrRange merged_range(intlv_ranges);
                    if (!(useDefaultRange &&
                          merged_range.isSubset(defaultRange))) {
                        xbarRanges.push_back(merged_range);
                        DPRINTF(AddrRanges, "-- Adding merged range %s\n",
                                merged_range.to_string());
                    }
                    intlv_ranges.clear();
                }
                intlv_ranges.push_back(r.first);
            } else {
                if (!(useDefaultRange &&
                      r.first.isSubset(defaultRange))) {
                    xbarRanges.push_back(r.first);
                    DPRINTF(AddrRanges, "-- Adding range %s\n",
                            r.first.to_string());
                }
            }
        }
        if (!intlv_ranges.empty()) {
            DPRINTF(AddrRanges, "-- Merging range from %d ranges\n",
                    intlv_ranges.size());
            AddrRange merged_range(intlv_ranges);
            if (!(useDefaultRange && merged_range.isSubset(defaultRange))) {
                xbarRanges.push_back(merged_range);
                DPRINTF(AddrRanges, "-- Adding merged range %s\n",
                        merged_range.to_string());
            }
        }
        if (useDefaultRange) {
            for (const auto& r: xbarRanges) {
                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 (const auto& port: cpuSidePorts)
            port->sendRangeChange();
    }
}
void BaseXBar :: recvRangeChange ( PortID mem_side_port_id ) { DPRINTF ( AddrRanges , " \n " , memSidePorts [ mem_side_port_id ] -> getPeer ( ) ) ; gotAddrRanges [ mem_side_port_id ] = true ; if ( ! gotAllAddrRanges ) { gotAllAddrRanges = true ; std :: vector < bool > :: const_iterator r = gotAddrRanges . begin ( ) ; while ( gotAllAddrRanges && r != gotAddrRanges . end ( ) ) { gotAllAddrRanges &= * r ++ ; } if ( gotAllAddrRanges ) DPRINTF ( AddrRanges , " \n " ) ; } if ( mem_side_port_id == defaultPortID ) { if ( useDefaultRange ) { AddrRangeList ranges = memSidePorts [ mem_side_port_id ] -> getAddrRanges ( ) ; if ( ranges . size ( ) != 1 ) fatal ( " " , name ( ) ) ; defaultRange = ranges . front ( ) ; } } else { if ( gotAddrRanges [ mem_side_port_id ] ) { for ( auto p = portMap . begin ( ) ; p != portMap . end ( ) ; ) { if ( p -> second == mem_side_port_id ) portMap . erase ( p ++ ) ; else p ++ ; } } AddrRangeList ranges = memSidePorts [ mem_side_port_id ] -> getAddrRanges ( ) ; for ( const auto & r : ranges ) { DPRINTF ( AddrRanges , " \n " , r . to_string ( ) , mem_side_port_id ) ; if ( portMap . insert ( r , mem_side_port_id ) == portMap . end ( ) ) { PortID conflict_id = portMap . intersects ( r ) -> second ; fatal ( " " " \n \t \n \t \n " , name ( ) , r . to_string ( ) , memSidePorts [ mem_side_port_id ] -> getPeer ( ) , memSidePorts [ conflict_id ] -> getPeer ( ) ) ; } } } if ( gotAllAddrRanges ) { DPRINTF ( AddrRanges , " \n " ) ; xbarRanges . clear ( ) ; if ( useDefaultRange ) { if ( ! gotAddrRanges [ defaultPortID ] ) fatal ( " " , name ( ) ) ; xbarRanges . push_back ( defaultRange ) ; DPRINTF ( AddrRanges , " \n " , defaultRange . to_string ( ) ) ; } std :: vector < AddrRange > intlv_ranges ; for ( const auto & r : portMap ) { if ( r . first . interleaved ( ) ) { if ( ! intlv_ranges . empty ( ) && ! intlv_ranges . back ( ) . mergesWith ( r . first ) ) { DPRINTF ( AddrRanges , " \n " , intlv_ranges . size ( ) ) ; AddrRange merged_range ( intlv_ranges ) ; if ( ! ( useDefaultRange && merged_range . isSubset ( defaultRange ) ) ) { xbarRanges . push_back ( merged_range ) ; DPRINTF ( AddrRanges , " \n " , merged_range . to_string ( ) ) ; } intlv_ranges . clear ( ) ; } intlv_ranges . push_back ( r . first ) ; } else { if ( ! ( useDefaultRange && r . first . isSubset ( defaultRange ) ) ) { xbarRanges . push_back ( r . first ) ; DPRINTF ( AddrRanges , " \n " , r . first . to_string ( ) ) ; } } } if ( ! intlv_ranges . empty ( ) ) { DPRINTF ( AddrRanges , " \n " , intlv_ranges . size ( ) ) ; AddrRange merged_range ( intlv_ranges ) ; if ( ! ( useDefaultRange && merged_range . isSubset ( defaultRange ) ) ) { xbarRanges . push_back ( merged_range ) ; DPRINTF ( AddrRanges , " \n " , merged_range . to_string ( ) ) ; } } if ( useDefaultRange ) { for ( const auto & r : xbarRanges ) { if ( r . intersects ( defaultRange ) && ! r . isSubset ( defaultRange ) ) fatal ( " " " " " \n " , r . to_string ( ) , name ( ) ) ; } } for ( const auto & port : cpuSidePorts ) port -> sendRangeChange ( ) ; } }
Function called by the port when the crossbar is receiving a range change.
Function called by the port when the crossbar is receiving a range change .
// remember that we got a range from this memory-side port and thus the // connected CPU-side-port module // update the global flag // take a logical AND of all the ports and see if we got // ranges from everyone // note that we could get the range from the default port at any // point in time, and we cannot assume that the default range is // set before the other ones are, so we do additional checks once // all ranges are provided // only update if we are indeed checking ranges for the // default port since the port might not have a valid range // otherwise // the ports are allowed to update their address ranges // dynamically, so remove any existing entries // erasing invalidates the iterator, so advance it // before the deletion takes place // if we have received ranges from all our neighbouring CPU-side-port // modules, go ahead and tell our connected memory-side-port modules in // turn, this effectively assumes a tree structure of the system // start out with the default range // merge all interleaved ranges and add any range that is not // a subset of the default range // if the range is interleaved then save it for now // 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 // next decide if we keep the merged range or not // keep the current range if not a subset of the default // if there is still interleaved ranges waiting to be merged, // go ahead and do it // also check that no range partially intersects 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 // see if the new range is partially // overlapping the default range // tell all our neighbouring memory-side ports that our address // ranges have changed