xbar.hh revision 4894
113245Sgabeblack@google.com/*
213245Sgabeblack@google.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
313245Sgabeblack@google.com * All rights reserved.
413245Sgabeblack@google.com *
513245Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
613245Sgabeblack@google.com * modification, are permitted provided that the following conditions are
713245Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
813245Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
913245Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1013245Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1113245Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1213245Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1313245Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1413245Sgabeblack@google.com * this software without specific prior written permission.
1513245Sgabeblack@google.com *
1613245Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1713245Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1813245Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1913245Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2013245Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2113245Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2213245Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2313245Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2413245Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2513245Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2613245Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2713245Sgabeblack@google.com *
2813245Sgabeblack@google.com * Authors: Ron Dreslinski
2913245Sgabeblack@google.com *          Ali Saidi
3013245Sgabeblack@google.com */
3113245Sgabeblack@google.com
3213245Sgabeblack@google.com/**
3313245Sgabeblack@google.com * @file
3413245Sgabeblack@google.com * Declaration of a bus object.
3513245Sgabeblack@google.com */
3613245Sgabeblack@google.com
3713245Sgabeblack@google.com#ifndef __MEM_BUS_HH__
3813245Sgabeblack@google.com#define __MEM_BUS_HH__
3913245Sgabeblack@google.com
4013245Sgabeblack@google.com#include <string>
4113245Sgabeblack@google.com#include <list>
4213245Sgabeblack@google.com#include <inttypes.h>
4313245Sgabeblack@google.com
4413245Sgabeblack@google.com#include "base/range.hh"
4513245Sgabeblack@google.com#include "base/hashmap.hh"
4613245Sgabeblack@google.com#include "base/range_map.hh"
4713245Sgabeblack@google.com#include "mem/mem_object.hh"
4813245Sgabeblack@google.com#include "mem/packet.hh"
4913245Sgabeblack@google.com#include "mem/port.hh"
5013245Sgabeblack@google.com#include "mem/request.hh"
5113245Sgabeblack@google.com#include "sim/eventq.hh"
5213245Sgabeblack@google.com
5313245Sgabeblack@google.comclass Bus : public MemObject
5413245Sgabeblack@google.com{
5513245Sgabeblack@google.com    /** Declaration of the buses port type, one will be instantiated for each
5613245Sgabeblack@google.com        of the interfaces connecting to the bus. */
5713245Sgabeblack@google.com    class BusPort : public Port
5813245Sgabeblack@google.com    {
5913245Sgabeblack@google.com        bool _onRetryList;
6013245Sgabeblack@google.com
6113245Sgabeblack@google.com        /** A pointer to the bus to which this port belongs. */
6213245Sgabeblack@google.com        Bus *bus;
6313245Sgabeblack@google.com
6413245Sgabeblack@google.com        /** A id to keep track of the intercafe ID this port is connected to. */
6513245Sgabeblack@google.com        int id;
6613245Sgabeblack@google.com
6713245Sgabeblack@google.com      public:
6813245Sgabeblack@google.com
6913245Sgabeblack@google.com        /** Constructor for the BusPort.*/
7013245Sgabeblack@google.com        BusPort(const std::string &_name, Bus *_bus, int _id)
7113245Sgabeblack@google.com            : Port(_name, _bus), _onRetryList(false), bus(_bus), id(_id)
7213245Sgabeblack@google.com        { }
7313245Sgabeblack@google.com
7413245Sgabeblack@google.com        bool onRetryList()
7513245Sgabeblack@google.com        { return _onRetryList; }
7613245Sgabeblack@google.com
7713245Sgabeblack@google.com        void onRetryList(bool newVal)
7813245Sgabeblack@google.com        { _onRetryList = newVal; }
7913245Sgabeblack@google.com
8013245Sgabeblack@google.com        int getId() { return id; }
8113245Sgabeblack@google.com
8213245Sgabeblack@google.com      protected:
8313245Sgabeblack@google.com
8413245Sgabeblack@google.com        /** When reciving a timing request from the peer port (at id),
8513245Sgabeblack@google.com            pass it to the bus. */
8613245Sgabeblack@google.com        virtual bool recvTiming(PacketPtr pkt)
8713245Sgabeblack@google.com        { pkt->setSrc(id); return bus->recvTiming(pkt); }
8813245Sgabeblack@google.com
8913245Sgabeblack@google.com        /** When reciving a Atomic requestfrom the peer port (at id),
9013245Sgabeblack@google.com            pass it to the bus. */
9113245Sgabeblack@google.com        virtual Tick recvAtomic(PacketPtr pkt)
9213245Sgabeblack@google.com        { pkt->setSrc(id); return bus->recvAtomic(pkt); }
9313245Sgabeblack@google.com
9413245Sgabeblack@google.com        /** When reciving a Functional requestfrom the peer port (at id),
9513245Sgabeblack@google.com            pass it to the bus. */
9613245Sgabeblack@google.com        virtual void recvFunctional(PacketPtr pkt)
9713245Sgabeblack@google.com        { pkt->setSrc(id); bus->recvFunctional(pkt); }
9813245Sgabeblack@google.com
9913245Sgabeblack@google.com        /** When reciving a status changefrom the peer port (at id),
10013245Sgabeblack@google.com            pass it to the bus. */
10113245Sgabeblack@google.com        virtual void recvStatusChange(Status status)
10213245Sgabeblack@google.com        { bus->recvStatusChange(status, id); }
10313245Sgabeblack@google.com
10413245Sgabeblack@google.com        /** When reciving a retry from the peer port (at id),
10513245Sgabeblack@google.com            pass it to the bus. */
10613245Sgabeblack@google.com        virtual void recvRetry()
10713245Sgabeblack@google.com        { bus->recvRetry(id); }
10813245Sgabeblack@google.com
10913245Sgabeblack@google.com        // This should return all the 'owned' addresses that are
11013245Sgabeblack@google.com        // downstream from this bus, yes?  That is, the union of all
11113245Sgabeblack@google.com        // the 'owned' address ranges of all the other interfaces on
11213245Sgabeblack@google.com        // this bus...
11313245Sgabeblack@google.com        virtual void getDeviceAddressRanges(AddrRangeList &resp,
11413245Sgabeblack@google.com                                            bool &snoop)
11513245Sgabeblack@google.com        { bus->addressRanges(resp, snoop, id); }
11613245Sgabeblack@google.com
11713245Sgabeblack@google.com        // Ask the bus to ask everyone on the bus what their block size is and
11813245Sgabeblack@google.com        // take the max of it. This might need to be changed a bit if we ever
11913245Sgabeblack@google.com        // support multiple block sizes.
12013245Sgabeblack@google.com        virtual int deviceBlockSize()
12113245Sgabeblack@google.com        { return bus->findBlockSize(id); }
12213245Sgabeblack@google.com
12313245Sgabeblack@google.com    };
12413245Sgabeblack@google.com
12513245Sgabeblack@google.com    class BusFreeEvent : public Event
12613245Sgabeblack@google.com    {
12713245Sgabeblack@google.com        Bus * bus;
12813245Sgabeblack@google.com
12913245Sgabeblack@google.com      public:
13013245Sgabeblack@google.com        BusFreeEvent(Bus * _bus);
13113245Sgabeblack@google.com        void process();
13213245Sgabeblack@google.com        const char *description();
13313245Sgabeblack@google.com    };
13413245Sgabeblack@google.com
13513245Sgabeblack@google.com    /** a globally unique id for this bus. */
13613245Sgabeblack@google.com    int busId;
13713245Sgabeblack@google.com    /** the clock speed for the bus */
13813245Sgabeblack@google.com    int clock;
13913245Sgabeblack@google.com    /** the width of the bus in bytes */
14013245Sgabeblack@google.com    int width;
14113245Sgabeblack@google.com    /** the next tick at which the bus will be idle */
14213245Sgabeblack@google.com    Tick tickNextIdle;
14313245Sgabeblack@google.com
14413245Sgabeblack@google.com    Event * drainEvent;
14513245Sgabeblack@google.com
14613245Sgabeblack@google.com
14713245Sgabeblack@google.com    static const int defaultId = -3; //Make it unique from Broadcast
14813245Sgabeblack@google.com
14913245Sgabeblack@google.com    typedef range_map<Addr,int>::iterator PortIter;
15013245Sgabeblack@google.com    range_map<Addr, int> portMap;
15113245Sgabeblack@google.com
15213245Sgabeblack@google.com    AddrRangeList defaultRange;
15313245Sgabeblack@google.com
15413245Sgabeblack@google.com    typedef std::vector<BusPort*>::iterator SnoopIter;
15513245Sgabeblack@google.com    std::vector<BusPort*> snoopPorts;
15613245Sgabeblack@google.com
15713245Sgabeblack@google.com    /** Function called by the port when the bus is recieving a Timing
15813245Sgabeblack@google.com      transaction.*/
15913245Sgabeblack@google.com    bool recvTiming(PacketPtr pkt);
16013245Sgabeblack@google.com
16113245Sgabeblack@google.com    /** Function called by the port when the bus is recieving a Atomic
16213245Sgabeblack@google.com      transaction.*/
16313245Sgabeblack@google.com    Tick recvAtomic(PacketPtr pkt);
16413245Sgabeblack@google.com
16513245Sgabeblack@google.com    /** Function called by the port when the bus is recieving a Functional
16613245Sgabeblack@google.com        transaction.*/
16713245Sgabeblack@google.com    void recvFunctional(PacketPtr pkt);
16813245Sgabeblack@google.com
16913245Sgabeblack@google.com    /** Timing function called by port when it is once again able to process
17013245Sgabeblack@google.com     * requests. */
17113245Sgabeblack@google.com    void recvRetry(int id);
17213245Sgabeblack@google.com
17313245Sgabeblack@google.com    /** Function called by the port when the bus is recieving a status change.*/
17413245Sgabeblack@google.com    void recvStatusChange(Port::Status status, int id);
17513245Sgabeblack@google.com
17613245Sgabeblack@google.com    /** Find which port connected to this bus (if any) should be given a packet
17713245Sgabeblack@google.com     * with this address.
17813245Sgabeblack@google.com     * @param addr Address to find port for.
17913245Sgabeblack@google.com     * @return id of port that the packet should be sent out of.
18013245Sgabeblack@google.com     */
18113245Sgabeblack@google.com    int findPort(Addr addr);
18213245Sgabeblack@google.com
18313245Sgabeblack@google.com    /** Snoop all relevant ports functionally. */
18413245Sgabeblack@google.com    void functionalSnoop(PacketPtr pkt, Port *responder);
18513245Sgabeblack@google.com
18613245Sgabeblack@google.com    /** Call snoop on caches, be sure to set SNOOP_COMMIT bit if you want
18713245Sgabeblack@google.com     * the snoop to happen
18813245Sgabeblack@google.com     * @return True if succeds.
18913245Sgabeblack@google.com     */
19013245Sgabeblack@google.com    bool timingSnoop(PacketPtr pkt, Port *responder);
19113245Sgabeblack@google.com
19213245Sgabeblack@google.com    /** Process address range request.
19313245Sgabeblack@google.com     * @param resp addresses that we can respond to
19413245Sgabeblack@google.com     * @param snoop addresses that we would like to snoop
19513245Sgabeblack@google.com     * @param id ide of the busport that made the request.
19613245Sgabeblack@google.com     */
19713245Sgabeblack@google.com    void addressRanges(AddrRangeList &resp, bool &snoop, int id);
19813245Sgabeblack@google.com
19913245Sgabeblack@google.com    /** Occupy the bus with transmitting the packet pkt */
20013245Sgabeblack@google.com    void occupyBus(PacketPtr pkt);
20113245Sgabeblack@google.com
20213245Sgabeblack@google.com    /** Ask everyone on the bus what their size is
20313245Sgabeblack@google.com     * @param id id of the busport that made the request
20413245Sgabeblack@google.com     * @return the max of all the sizes
20513245Sgabeblack@google.com     */
20613245Sgabeblack@google.com    int findBlockSize(int id);
20713245Sgabeblack@google.com
20813245Sgabeblack@google.com    BusFreeEvent busIdle;
20913245Sgabeblack@google.com
21013245Sgabeblack@google.com    bool inRetry;
21113245Sgabeblack@google.com
21213245Sgabeblack@google.com    /** max number of bus ids we've handed out so far */
21313245Sgabeblack@google.com    short maxId;
21413245Sgabeblack@google.com
21513245Sgabeblack@google.com    /** An array of pointers to the peer port interfaces
21613245Sgabeblack@google.com        connected to this bus.*/
21713245Sgabeblack@google.com    m5::hash_map<short,BusPort*> interfaces;
21813245Sgabeblack@google.com
21913245Sgabeblack@google.com    /** An array of pointers to ports that retry should be called on because the
22013245Sgabeblack@google.com     * original send failed for whatever reason.*/
22113245Sgabeblack@google.com    std::list<BusPort*> retryList;
22213245Sgabeblack@google.com
22313245Sgabeblack@google.com    void addToRetryList(BusPort * port)
22413245Sgabeblack@google.com    {
22513245Sgabeblack@google.com        if (!inRetry) {
22613245Sgabeblack@google.com            // The device wasn't retrying a packet, or wasn't at an appropriate
22713245Sgabeblack@google.com            // time.
22813245Sgabeblack@google.com            assert(!port->onRetryList());
22913245Sgabeblack@google.com            port->onRetryList(true);
23013245Sgabeblack@google.com            retryList.push_back(port);
23113245Sgabeblack@google.com        } else {
23213245Sgabeblack@google.com            if (port->onRetryList()) {
23313245Sgabeblack@google.com                // The device was retrying a packet. It didn't work, so we'll leave
23413245Sgabeblack@google.com                // it at the head of the retry list.
23513245Sgabeblack@google.com                assert(port == retryList.front());
23613245Sgabeblack@google.com                inRetry = false;
23713245Sgabeblack@google.com            }
23813245Sgabeblack@google.com            else {
23913245Sgabeblack@google.com                port->onRetryList(true);
24013245Sgabeblack@google.com                retryList.push_back(port);
24113245Sgabeblack@google.com            }
24213245Sgabeblack@google.com        }
24313245Sgabeblack@google.com    }
24413245Sgabeblack@google.com
24513245Sgabeblack@google.com    /** Port that handles requests that don't match any of the interfaces.*/
24613245Sgabeblack@google.com    BusPort *defaultPort;
24713245Sgabeblack@google.com
24813245Sgabeblack@google.com    BusPort *funcPort;
24913245Sgabeblack@google.com    int funcPortId;
25013245Sgabeblack@google.com
25113245Sgabeblack@google.com    /** Has the user specified their own default responder? */
25213245Sgabeblack@google.com    bool responderSet;
25313245Sgabeblack@google.com
25413245Sgabeblack@google.com    int defaultBlockSize;
25513245Sgabeblack@google.com    int cachedBlockSize;
25613245Sgabeblack@google.com    bool cachedBlockSizeValid;
25713245Sgabeblack@google.com
25813245Sgabeblack@google.com  public:
25913245Sgabeblack@google.com
26013245Sgabeblack@google.com    /** A function used to return the port associated with this bus object. */
26113245Sgabeblack@google.com    virtual Port *getPort(const std::string &if_name, int idx = -1);
26213245Sgabeblack@google.com    virtual void deletePortRefs(Port *p);
26313245Sgabeblack@google.com
26413245Sgabeblack@google.com    virtual void init();
26513245Sgabeblack@google.com    virtual void startup();
26613245Sgabeblack@google.com
26713245Sgabeblack@google.com    unsigned int drain(Event *de);
26813245Sgabeblack@google.com
26913245Sgabeblack@google.com    Bus(const std::string &n, int bus_id, int _clock, int _width,
27013245Sgabeblack@google.com        bool responder_set, int dflt_blk_size)
27113245Sgabeblack@google.com        : MemObject(n), busId(bus_id), clock(_clock), width(_width),
27213245Sgabeblack@google.com          tickNextIdle(0), drainEvent(NULL), busIdle(this), inRetry(false),
27313245Sgabeblack@google.com          maxId(0), defaultPort(NULL), funcPort(NULL), funcPortId(-4),
27413245Sgabeblack@google.com          responderSet(responder_set), defaultBlockSize(dflt_blk_size),
27513245Sgabeblack@google.com          cachedBlockSize(0), cachedBlockSizeValid(false)
27613245Sgabeblack@google.com    {
27713245Sgabeblack@google.com        //Both the width and clock period must be positive
27813245Sgabeblack@google.com        if (width <= 0)
27913245Sgabeblack@google.com            fatal("Bus width must be positive\n");
28013245Sgabeblack@google.com        if (clock <= 0)
28113245Sgabeblack@google.com            fatal("Bus clock period must be positive\n");
28213245Sgabeblack@google.com    }
28313245Sgabeblack@google.com
28413245Sgabeblack@google.com};
28513245Sgabeblack@google.com
28613245Sgabeblack@google.com#endif //__MEM_BUS_HH__
28713245Sgabeblack@google.com