noncoherent_xbar.hh revision 4475
110259SAndrew.Bardsley@arm.com/*
212355Snikos.nikoleris@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
310259SAndrew.Bardsley@arm.com * All rights reserved.
410259SAndrew.Bardsley@arm.com *
510259SAndrew.Bardsley@arm.com * Redistribution and use in source and binary forms, with or without
610259SAndrew.Bardsley@arm.com * modification, are permitted provided that the following conditions are
710259SAndrew.Bardsley@arm.com * met: redistributions of source code must retain the above copyright
810259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer;
910259SAndrew.Bardsley@arm.com * redistributions in binary form must reproduce the above copyright
1010259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer in the
1110259SAndrew.Bardsley@arm.com * documentation and/or other materials provided with the distribution;
1210259SAndrew.Bardsley@arm.com * neither the name of the copyright holders nor the names of its
1310259SAndrew.Bardsley@arm.com * contributors may be used to endorse or promote products derived from
1410259SAndrew.Bardsley@arm.com * this software without specific prior written permission.
1510259SAndrew.Bardsley@arm.com *
1610259SAndrew.Bardsley@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710259SAndrew.Bardsley@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1810259SAndrew.Bardsley@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1910259SAndrew.Bardsley@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2010259SAndrew.Bardsley@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110259SAndrew.Bardsley@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210259SAndrew.Bardsley@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2310259SAndrew.Bardsley@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2410259SAndrew.Bardsley@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2510259SAndrew.Bardsley@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2610259SAndrew.Bardsley@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2710259SAndrew.Bardsley@arm.com *
2810259SAndrew.Bardsley@arm.com * Authors: Ron Dreslinski
2910259SAndrew.Bardsley@arm.com *          Ali Saidi
3010259SAndrew.Bardsley@arm.com */
3110259SAndrew.Bardsley@arm.com
3210259SAndrew.Bardsley@arm.com/**
3310259SAndrew.Bardsley@arm.com * @file
3410259SAndrew.Bardsley@arm.com * Declaration of a bus object.
3510259SAndrew.Bardsley@arm.com */
3610259SAndrew.Bardsley@arm.com
3710259SAndrew.Bardsley@arm.com#ifndef __MEM_BUS_HH__
3810259SAndrew.Bardsley@arm.com#define __MEM_BUS_HH__
3910259SAndrew.Bardsley@arm.com
4011793Sbrandon.potter@amd.com#include <string>
4111793Sbrandon.potter@amd.com#include <list>
4210259SAndrew.Bardsley@arm.com#include <inttypes.h>
4310259SAndrew.Bardsley@arm.com
4410259SAndrew.Bardsley@arm.com#include "base/range.hh"
4510259SAndrew.Bardsley@arm.com#include "base/hashmap.hh"
4610259SAndrew.Bardsley@arm.com#include "base/range_map.hh"
4710259SAndrew.Bardsley@arm.com#include "mem/mem_object.hh"
4810259SAndrew.Bardsley@arm.com#include "mem/packet.hh"
4910259SAndrew.Bardsley@arm.com#include "mem/port.hh"
5010259SAndrew.Bardsley@arm.com#include "mem/request.hh"
5110259SAndrew.Bardsley@arm.com#include "sim/eventq.hh"
5210259SAndrew.Bardsley@arm.com
5310259SAndrew.Bardsley@arm.comclass Bus : public MemObject
5410259SAndrew.Bardsley@arm.com{
5510259SAndrew.Bardsley@arm.com    /** Declaration of the buses port type, one will be instantiated for each
5610259SAndrew.Bardsley@arm.com        of the interfaces connecting to the bus. */
5710259SAndrew.Bardsley@arm.com    class BusPort : public Port
5810259SAndrew.Bardsley@arm.com    {
5910259SAndrew.Bardsley@arm.com        bool _onRetryList;
6010259SAndrew.Bardsley@arm.com
6110259SAndrew.Bardsley@arm.com        /** A pointer to the bus to which this port belongs. */
6210259SAndrew.Bardsley@arm.com        Bus *bus;
6310259SAndrew.Bardsley@arm.com
6410259SAndrew.Bardsley@arm.com        /** A id to keep track of the intercafe ID this port is connected to. */
6510259SAndrew.Bardsley@arm.com        int id;
6610259SAndrew.Bardsley@arm.com
6710259SAndrew.Bardsley@arm.com      public:
6810259SAndrew.Bardsley@arm.com
6910259SAndrew.Bardsley@arm.com        /** Constructor for the BusPort.*/
7010259SAndrew.Bardsley@arm.com        BusPort(const std::string &_name, Bus *_bus, int _id)
7110259SAndrew.Bardsley@arm.com            : Port(_name, _bus), _onRetryList(false), bus(_bus), id(_id)
7210259SAndrew.Bardsley@arm.com        { }
7310259SAndrew.Bardsley@arm.com
7410259SAndrew.Bardsley@arm.com        bool onRetryList()
7510259SAndrew.Bardsley@arm.com        { return _onRetryList; }
7610259SAndrew.Bardsley@arm.com
7710259SAndrew.Bardsley@arm.com        void onRetryList(bool newVal)
7810259SAndrew.Bardsley@arm.com        { _onRetryList = newVal; }
7910259SAndrew.Bardsley@arm.com
8010259SAndrew.Bardsley@arm.com        int getId() { return id; }
8110259SAndrew.Bardsley@arm.com
8210259SAndrew.Bardsley@arm.com      protected:
8310259SAndrew.Bardsley@arm.com
8410259SAndrew.Bardsley@arm.com        /** When reciving a timing request from the peer port (at id),
8510259SAndrew.Bardsley@arm.com            pass it to the bus. */
8610259SAndrew.Bardsley@arm.com        virtual bool recvTiming(PacketPtr pkt)
8710259SAndrew.Bardsley@arm.com        { pkt->setSrc(id); return bus->recvTiming(pkt); }
8810259SAndrew.Bardsley@arm.com
8910259SAndrew.Bardsley@arm.com        /** When reciving a Atomic requestfrom the peer port (at id),
9010259SAndrew.Bardsley@arm.com            pass it to the bus. */
9110259SAndrew.Bardsley@arm.com        virtual Tick recvAtomic(PacketPtr pkt)
9210259SAndrew.Bardsley@arm.com        { pkt->setSrc(id); return bus->recvAtomic(pkt); }
9310259SAndrew.Bardsley@arm.com
9410259SAndrew.Bardsley@arm.com        /** When reciving a Functional requestfrom the peer port (at id),
9510259SAndrew.Bardsley@arm.com            pass it to the bus. */
9610259SAndrew.Bardsley@arm.com        virtual void recvFunctional(PacketPtr pkt)
9710259SAndrew.Bardsley@arm.com        { pkt->setSrc(id); bus->recvFunctional(pkt); }
9810259SAndrew.Bardsley@arm.com
9910259SAndrew.Bardsley@arm.com        /** When reciving a status changefrom the peer port (at id),
10012179Spau.cabre@metempsy.com            pass it to the bus. */
10110259SAndrew.Bardsley@arm.com        virtual void recvStatusChange(Status status)
10210259SAndrew.Bardsley@arm.com        { bus->recvStatusChange(status, id); }
10310259SAndrew.Bardsley@arm.com
10410259SAndrew.Bardsley@arm.com        /** When reciving a retry from the peer port (at id),
10510259SAndrew.Bardsley@arm.com            pass it to the bus. */
10610259SAndrew.Bardsley@arm.com        virtual void recvRetry()
10710259SAndrew.Bardsley@arm.com        { bus->recvRetry(id); }
10810259SAndrew.Bardsley@arm.com
10910259SAndrew.Bardsley@arm.com        // This should return all the 'owned' addresses that are
11010259SAndrew.Bardsley@arm.com        // downstream from this bus, yes?  That is, the union of all
11110259SAndrew.Bardsley@arm.com        // the 'owned' address ranges of all the other interfaces on
11210259SAndrew.Bardsley@arm.com        // this bus...
11310259SAndrew.Bardsley@arm.com        virtual void getDeviceAddressRanges(AddrRangeList &resp,
11410259SAndrew.Bardsley@arm.com                                            bool &snoop)
11510259SAndrew.Bardsley@arm.com        { bus->addressRanges(resp, snoop, id); }
11610259SAndrew.Bardsley@arm.com
11710259SAndrew.Bardsley@arm.com        // Ask the bus to ask everyone on the bus what their block size is and
11810259SAndrew.Bardsley@arm.com        // take the max of it. This might need to be changed a bit if we ever
11910259SAndrew.Bardsley@arm.com        // support multiple block sizes.
12010259SAndrew.Bardsley@arm.com        virtual int deviceBlockSize()
12110259SAndrew.Bardsley@arm.com        { return bus->findBlockSize(id); }
12210259SAndrew.Bardsley@arm.com
12310259SAndrew.Bardsley@arm.com    };
12410259SAndrew.Bardsley@arm.com
12510259SAndrew.Bardsley@arm.com    class BusFreeEvent : public Event
12610259SAndrew.Bardsley@arm.com    {
12710259SAndrew.Bardsley@arm.com        Bus * bus;
12810259SAndrew.Bardsley@arm.com
12910259SAndrew.Bardsley@arm.com      public:
13010259SAndrew.Bardsley@arm.com        BusFreeEvent(Bus * _bus);
13110259SAndrew.Bardsley@arm.com        void process();
13210259SAndrew.Bardsley@arm.com        const char *description();
13310259SAndrew.Bardsley@arm.com    };
13410259SAndrew.Bardsley@arm.com
13510259SAndrew.Bardsley@arm.com    /** a globally unique id for this bus. */
13610259SAndrew.Bardsley@arm.com    int busId;
13710259SAndrew.Bardsley@arm.com    /** the clock speed for the bus */
13810259SAndrew.Bardsley@arm.com    int clock;
13910259SAndrew.Bardsley@arm.com    /** the width of the bus in bytes */
14010259SAndrew.Bardsley@arm.com    int width;
14110259SAndrew.Bardsley@arm.com    /** the next tick at which the bus will be idle */
14210259SAndrew.Bardsley@arm.com    Tick tickNextIdle;
14310259SAndrew.Bardsley@arm.com
14410259SAndrew.Bardsley@arm.com    Event * drainEvent;
14510259SAndrew.Bardsley@arm.com
14610259SAndrew.Bardsley@arm.com
14710259SAndrew.Bardsley@arm.com    static const int defaultId = -3; //Make it unique from Broadcast
14810259SAndrew.Bardsley@arm.com
14910259SAndrew.Bardsley@arm.com    typedef range_map<Addr,int>::iterator PortIter;
15010259SAndrew.Bardsley@arm.com    range_map<Addr, int> portMap;
15110259SAndrew.Bardsley@arm.com
15210259SAndrew.Bardsley@arm.com    AddrRangeList defaultRange;
15310259SAndrew.Bardsley@arm.com
15410259SAndrew.Bardsley@arm.com    typedef std::vector<BusPort*>::iterator SnoopIter;
15510259SAndrew.Bardsley@arm.com    std::vector<BusPort*> snoopPorts;
15610259SAndrew.Bardsley@arm.com
15710259SAndrew.Bardsley@arm.com    /** Function called by the port when the bus is recieving a Timing
15810259SAndrew.Bardsley@arm.com      transaction.*/
15910259SAndrew.Bardsley@arm.com    bool recvTiming(PacketPtr pkt);
16010259SAndrew.Bardsley@arm.com
16110259SAndrew.Bardsley@arm.com    /** Function called by the port when the bus is recieving a Atomic
16210259SAndrew.Bardsley@arm.com      transaction.*/
16310259SAndrew.Bardsley@arm.com    Tick recvAtomic(PacketPtr pkt);
16410259SAndrew.Bardsley@arm.com
16510259SAndrew.Bardsley@arm.com    /** Function called by the port when the bus is recieving a Functional
16610259SAndrew.Bardsley@arm.com        transaction.*/
16710259SAndrew.Bardsley@arm.com    void recvFunctional(PacketPtr pkt);
16810259SAndrew.Bardsley@arm.com
16910259SAndrew.Bardsley@arm.com    /** Timing function called by port when it is once again able to process
17010259SAndrew.Bardsley@arm.com     * requests. */
17110259SAndrew.Bardsley@arm.com    void recvRetry(int id);
17210259SAndrew.Bardsley@arm.com
17310259SAndrew.Bardsley@arm.com    /** Function called by the port when the bus is recieving a status change.*/
17410259SAndrew.Bardsley@arm.com    void recvStatusChange(Port::Status status, int id);
17510259SAndrew.Bardsley@arm.com
17610259SAndrew.Bardsley@arm.com    /** Find which port connected to this bus (if any) should be given a packet
17710259SAndrew.Bardsley@arm.com     * with this address.
17810259SAndrew.Bardsley@arm.com     * @param addr Address to find port for.
17910259SAndrew.Bardsley@arm.com     * @param id Id of the port this packet was received from (to prevent
18010259SAndrew.Bardsley@arm.com     *             loops)
18110259SAndrew.Bardsley@arm.com     * @return pointer to port that the packet should be sent out of.
18210259SAndrew.Bardsley@arm.com     */
18310259SAndrew.Bardsley@arm.com    Port *findPort(Addr addr, int id);
18410259SAndrew.Bardsley@arm.com
18510259SAndrew.Bardsley@arm.com    /** Snoop all relevant ports atomicly. */
18610259SAndrew.Bardsley@arm.com    Tick atomicSnoop(PacketPtr pkt, Port* responder);
18710259SAndrew.Bardsley@arm.com
18810259SAndrew.Bardsley@arm.com    /** Snoop all relevant ports functionally. */
18910259SAndrew.Bardsley@arm.com    void functionalSnoop(PacketPtr pkt, Port *responder);
19010259SAndrew.Bardsley@arm.com
19110259SAndrew.Bardsley@arm.com    /** Call snoop on caches, be sure to set SNOOP_COMMIT bit if you want
19210259SAndrew.Bardsley@arm.com     * the snoop to happen
19310259SAndrew.Bardsley@arm.com     * @return True if succeds.
19410259SAndrew.Bardsley@arm.com     */
19510259SAndrew.Bardsley@arm.com    bool timingSnoop(PacketPtr pkt, Port *responder);
19610259SAndrew.Bardsley@arm.com
19710259SAndrew.Bardsley@arm.com    /** Process address range request.
19810259SAndrew.Bardsley@arm.com     * @param resp addresses that we can respond to
19910259SAndrew.Bardsley@arm.com     * @param snoop addresses that we would like to snoop
20010259SAndrew.Bardsley@arm.com     * @param id ide of the busport that made the request.
20110259SAndrew.Bardsley@arm.com     */
20210259SAndrew.Bardsley@arm.com    void addressRanges(AddrRangeList &resp, bool &snoop, int id);
20310259SAndrew.Bardsley@arm.com
20410259SAndrew.Bardsley@arm.com    /** Occupy the bus with transmitting the packet pkt */
20510259SAndrew.Bardsley@arm.com    void occupyBus(PacketPtr pkt);
20610259SAndrew.Bardsley@arm.com
20710259SAndrew.Bardsley@arm.com    /** Ask everyone on the bus what their size is
20810259SAndrew.Bardsley@arm.com     * @param id id of the busport that made the request
20910259SAndrew.Bardsley@arm.com     * @return the max of all the sizes
21010259SAndrew.Bardsley@arm.com     */
21110259SAndrew.Bardsley@arm.com    int findBlockSize(int id);
21210259SAndrew.Bardsley@arm.com
21310259SAndrew.Bardsley@arm.com    BusFreeEvent busIdle;
21410259SAndrew.Bardsley@arm.com
21510259SAndrew.Bardsley@arm.com    bool inRetry;
21610259SAndrew.Bardsley@arm.com
21710259SAndrew.Bardsley@arm.com    /** max number of bus ids we've handed out so far */
21810259SAndrew.Bardsley@arm.com    short maxId;
21910259SAndrew.Bardsley@arm.com
22011567Smitch.hayenga@arm.com    /** An array of pointers to the peer port interfaces
22111567Smitch.hayenga@arm.com        connected to this bus.*/
22210259SAndrew.Bardsley@arm.com    m5::hash_map<short,BusPort*> interfaces;
22310259SAndrew.Bardsley@arm.com
22410259SAndrew.Bardsley@arm.com    /** An array of pointers to ports that retry should be called on because the
22510259SAndrew.Bardsley@arm.com     * original send failed for whatever reason.*/
22610259SAndrew.Bardsley@arm.com    std::list<BusPort*> retryList;
22711567Smitch.hayenga@arm.com
22810259SAndrew.Bardsley@arm.com    void addToRetryList(BusPort * port)
22910259SAndrew.Bardsley@arm.com    {
23010259SAndrew.Bardsley@arm.com        if (!inRetry) {
23110379Sandreas.hansson@arm.com            // The device wasn't retrying a packet, or wasn't at an appropriate
23210379Sandreas.hansson@arm.com            // time.
23310259SAndrew.Bardsley@arm.com            assert(!port->onRetryList());
23410259SAndrew.Bardsley@arm.com            port->onRetryList(true);
23510259SAndrew.Bardsley@arm.com            retryList.push_back(port);
23610259SAndrew.Bardsley@arm.com        } else {
23710259SAndrew.Bardsley@arm.com            if (port->onRetryList()) {
23810259SAndrew.Bardsley@arm.com                // The device was retrying a packet. It didn't work, so we'll leave
23910259SAndrew.Bardsley@arm.com                // it at the head of the retry list.
24010259SAndrew.Bardsley@arm.com                assert(port == retryList.front());
24110259SAndrew.Bardsley@arm.com                inRetry = false;
24210259SAndrew.Bardsley@arm.com            }
24310259SAndrew.Bardsley@arm.com            else {
24410259SAndrew.Bardsley@arm.com                port->onRetryList(true);
24510259SAndrew.Bardsley@arm.com                retryList.push_back(port);
24610259SAndrew.Bardsley@arm.com            }
24710259SAndrew.Bardsley@arm.com        }
24810259SAndrew.Bardsley@arm.com    }
24910259SAndrew.Bardsley@arm.com
25010259SAndrew.Bardsley@arm.com    /** Port that handles requests that don't match any of the interfaces.*/
25110259SAndrew.Bardsley@arm.com    BusPort *defaultPort;
25210259SAndrew.Bardsley@arm.com
25310259SAndrew.Bardsley@arm.com    BusPort *funcPort;
25410259SAndrew.Bardsley@arm.com    int funcPortId;
25510259SAndrew.Bardsley@arm.com
25610259SAndrew.Bardsley@arm.com    /** Has the user specified their own default responder? */
25710259SAndrew.Bardsley@arm.com    bool responderSet;
25810259SAndrew.Bardsley@arm.com
25910259SAndrew.Bardsley@arm.com    int defaultBlockSize;
26010259SAndrew.Bardsley@arm.com    int cachedBlockSize;
26110259SAndrew.Bardsley@arm.com    bool cachedBlockSizeValid;
26210259SAndrew.Bardsley@arm.com
26310259SAndrew.Bardsley@arm.com  public:
26410259SAndrew.Bardsley@arm.com
26510259SAndrew.Bardsley@arm.com    /** A function used to return the port associated with this bus object. */
26610259SAndrew.Bardsley@arm.com    virtual Port *getPort(const std::string &if_name, int idx = -1);
26710259SAndrew.Bardsley@arm.com    virtual void deletePortRefs(Port *p);
26810259SAndrew.Bardsley@arm.com
26910259SAndrew.Bardsley@arm.com    virtual void init();
27010259SAndrew.Bardsley@arm.com
27110259SAndrew.Bardsley@arm.com    unsigned int drain(Event *de);
27210259SAndrew.Bardsley@arm.com
27310259SAndrew.Bardsley@arm.com    Bus(const std::string &n, int bus_id, int _clock, int _width,
27410259SAndrew.Bardsley@arm.com        bool responder_set, int dflt_blk_size)
27510259SAndrew.Bardsley@arm.com        : MemObject(n), busId(bus_id), clock(_clock), width(_width),
27610259SAndrew.Bardsley@arm.com          tickNextIdle(0), drainEvent(NULL), busIdle(this), inRetry(false),
27710259SAndrew.Bardsley@arm.com          maxId(0), defaultPort(NULL), funcPort(NULL), funcPortId(-4),
27810379Sandreas.hansson@arm.com          responderSet(responder_set), defaultBlockSize(dflt_blk_size),
27910379Sandreas.hansson@arm.com          cachedBlockSize(0), cachedBlockSizeValid(false)
28010259SAndrew.Bardsley@arm.com    {
28110259SAndrew.Bardsley@arm.com        //Both the width and clock period must be positive
28210259SAndrew.Bardsley@arm.com        if (width <= 0)
28310259SAndrew.Bardsley@arm.com            fatal("Bus width must be positive\n");
28410259SAndrew.Bardsley@arm.com        if (clock <= 0)
28510259SAndrew.Bardsley@arm.com            fatal("Bus clock period must be positive\n");
28610259SAndrew.Bardsley@arm.com    }
28710259SAndrew.Bardsley@arm.com
28810259SAndrew.Bardsley@arm.com};
28910259SAndrew.Bardsley@arm.com
29010259SAndrew.Bardsley@arm.com#endif //__MEM_BUS_HH__
29110259SAndrew.Bardsley@arm.com