coherent_xbar.cc revision 2568
16145SN/A/*
28683SN/A * Copyright (c) 2006 The Regents of The University of Michigan
310973Sdavid.hashe@amd.com * All rights reserved.
46145SN/A *
56145SN/A * Redistribution and use in source and binary forms, with or without
66145SN/A * modification, are permitted provided that the following conditions are
76145SN/A * met: redistributions of source code must retain the above copyright
86145SN/A * notice, this list of conditions and the following disclaimer;
96145SN/A * redistributions in binary form must reproduce the above copyright
106145SN/A * notice, this list of conditions and the following disclaimer in the
116145SN/A * documentation and/or other materials provided with the distribution;
126145SN/A * neither the name of the copyright holders nor the names of its
136145SN/A * contributors may be used to endorse or promote products derived from
146145SN/A * this software without specific prior written permission.
156145SN/A *
166145SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176145SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186145SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196145SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206145SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216145SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226145SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236145SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246145SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256145SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266145SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276145SN/A */
286145SN/A
296145SN/A/**
3010441Snilay@cs.wisc.edu * @file Definition of a bus object.
3110441Snilay@cs.wisc.edu */
326145SN/A
337055SN/A
346145SN/A#include "base/trace.hh"
356145SN/A#include "mem/bus.hh"
367039SN/A#include "sim/builder.hh"
379104SN/A
3810301Snilay@cs.wisc.edu/** Get the ranges of anyone that we are connected to. */
399105SN/Avoid
408174SN/ABus::init()
417039SN/A{
427039SN/A    std::vector<Port*>::iterator intIter;
437039SN/A    for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
4410970Sdavid.hashe@amd.com        (*intIter)->sendStatusChange(Port::RangeChange);
4510301Snilay@cs.wisc.edu}
4610301Snilay@cs.wisc.edu
477039SN/A
487039SN/A/** Function called by the port when the bus is recieving a Timing
496145SN/A * transaction.*/
507039SN/Abool
517039SN/ABus::recvTiming(Packet &pkt, int id)
527039SN/A{
536876SN/A    return findPort(pkt.addr, id)->sendTiming(pkt);
547039SN/A}
557039SN/A
566145SN/APort *
577039SN/ABus::findPort(Addr addr, int id)
586145SN/A{
5911049Snilay@cs.wisc.edu    /* An interval tree would be a better way to do this. --ali. */
6011049Snilay@cs.wisc.edu    int dest_id = -1;
6111049Snilay@cs.wisc.edu    int i = 0;
6211049Snilay@cs.wisc.edu    bool found = false;
6311049Snilay@cs.wisc.edu
6411049Snilay@cs.wisc.edu    while (i < portList.size() && !found)
6511049Snilay@cs.wisc.edu    {
6611049Snilay@cs.wisc.edu        if (portList[i].range == addr) {
6711049Snilay@cs.wisc.edu            dest_id = portList[i].portId;
687039SN/A            found = true;
6911025Snilay@cs.wisc.edu            DPRINTF(Bus, "Found Addr: %llx on device %d\n", addr, dest_id);
706145SN/A        }
717039SN/A        i++;
727039SN/A    }
737039SN/A    if (dest_id == -1)
7411025Snilay@cs.wisc.edu        panic("Unable to find destination for addr: %llx", addr);
756145SN/A
767039SN/A    // we shouldn't be sending this back to where it came from
7711025Snilay@cs.wisc.edu    assert(dest_id != id);
7810974Sdavid.hashe@amd.com
7911025Snilay@cs.wisc.edu    return interfaces[dest_id];
8010974Sdavid.hashe@amd.com}
8110974Sdavid.hashe@amd.com
8210974Sdavid.hashe@amd.com/** Function called by the port when the bus is recieving a Atomic
8311025Snilay@cs.wisc.edu * transaction.*/
848193SN/ATick
8510974Sdavid.hashe@amd.comBus::recvAtomic(Packet &pkt, int id)
868193SN/A{
876145SN/A    return findPort(pkt.addr, id)->sendAtomic(pkt);
887039SN/A}
8911025Snilay@cs.wisc.edu
906145SN/A/** Function called by the port when the bus is recieving a Functional
917039SN/A * transaction.*/
9211025Snilay@cs.wisc.eduvoid
936145SN/ABus::recvFunctional(Packet &pkt, int id)
947039SN/A{
9511025Snilay@cs.wisc.edu    findPort(pkt.addr, id)->sendFunctional(pkt);
9611025Snilay@cs.wisc.edu}
976145SN/A
9810969Sdavid.hashe@amd.com/** Function called by the port when the bus is recieving a status change.*/
9910969Sdavid.hashe@amd.comvoid
10010969Sdavid.hashe@amd.comBus::recvStatusChange(Port::Status status, int id)
10111061Snilay@cs.wisc.edu{
10211061Snilay@cs.wisc.edu    DPRINTF(Bus, "Bus %d recieved status change from device id %d\n",
1036285SN/A            busId, id);
1047039SN/A    assert(status == Port::RangeChange &&
1058683SN/A           "The other statuses need to be implemented.");
1066145SN/A
1077039SN/A    assert(id < interfaces.size() && id >= 0);
10811025Snilay@cs.wisc.edu    int x;
1096145SN/A    Port *port = interfaces[id];
11011059Snilay@cs.wisc.edu    AddrRangeList ranges;
11111059Snilay@cs.wisc.edu    AddrRangeList snoops;
11211059Snilay@cs.wisc.edu    AddrRangeIter iter;
11311059Snilay@cs.wisc.edu    std::vector<DevMap>::iterator portIter;
11411059Snilay@cs.wisc.edu
11511025Snilay@cs.wisc.edu    // Clean out any previously existent ids
11611025Snilay@cs.wisc.edu    for (portIter = portList.begin(); portIter != portList.end(); ) {
11711025Snilay@cs.wisc.edu        if (portIter->portId == id)
1189692SN/A            portIter = portList.erase(portIter);
1197039SN/A        else
1207055SN/A            portIter++;
1217055SN/A    }
1226145SN/A
1239692SN/A    port->getPeerAddressRanges(ranges, snoops);
12411025Snilay@cs.wisc.edu
12511025Snilay@cs.wisc.edu    // not dealing with snooping yet either
1266374SN/A    assert(snoops.size() == 0);
1279692SN/A    for(iter = ranges.begin(); iter != ranges.end(); iter++) {
1289692SN/A        DevMap dm;
1299692SN/A        dm.portId = id;
1309692SN/A        dm.range = *iter;
1319692SN/A
1329692SN/A        DPRINTF(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start,
1339692SN/A                dm.range.end, id);
1349692SN/A        portList.push_back(dm);
1359692SN/A    }
1369692SN/A    DPRINTF(MMU, "port list has %d entries\n", portList.size());
1379104SN/A
1389104SN/A    // tell all our peers that our address range has changed.
1399104SN/A    // Don't tell the device that caused this change, it already knows
1409104SN/A    for (x = 0; x < interfaces.size(); x++)
1419104SN/A        if (x != id)
1429104SN/A            interfaces[x]->sendStatusChange(Port::RangeChange);
1439105SN/A}
1449105SN/A
1459692SN/Avoid
14610973Sdavid.hashe@amd.comBus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id)
14710973Sdavid.hashe@amd.com{
14811025Snilay@cs.wisc.edu    std::vector<DevMap>::iterator portIter;
14910973Sdavid.hashe@amd.com
1507039SN/A    resp.clear();
1517039SN/A    snoop.clear();
15211061Snilay@cs.wisc.edu
1536145SN/A    DPRINTF(Bus, "Bus id %d recieved address range request returning\n",
1547039SN/A            busId);
1557039SN/A    for (portIter = portList.begin(); portIter != portList.end(); portIter++) {
15611061Snilay@cs.wisc.edu        if (portIter->portId != id) {
15711061Snilay@cs.wisc.edu            resp.push_back(portIter->range);
1586145SN/A            DPRINTF(Bus, "-- %#llX : %#llX\n", portIter->range.start,
1597039SN/A                    portIter->range.end);
1607039SN/A        }
1617039SN/A    }
1626145SN/A}
1637039SN/A
1647039SN/ABEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus)
1657039SN/A
1666285SN/A    Param<int> bus_id;
1677039SN/A
1687039SN/AEND_DECLARE_SIM_OBJECT_PARAMS(Bus)
16911025Snilay@cs.wisc.edu
1707454SN/ABEGIN_INIT_SIM_OBJECT_PARAMS(Bus)
1716145SN/A    INIT_PARAM(bus_id, "a globally unique bus id")
1727039SN/AEND_INIT_SIM_OBJECT_PARAMS(Bus)
1736145SN/A
1749105SN/ACREATE_SIM_OBJECT(Bus)
1759105SN/A{
1769105SN/A    return new Bus(getInstanceName(), bus_id);
1777039SN/A}
1787039SN/A
1797039SN/AREGISTER_SIM_OBJECT("Bus", Bus)
1807039SN/A