xbar.hh revision 3470
12SN/A/*
21762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski
292665Ssaidi@eecs.umich.edu *          Ali Saidi
302SN/A */
312SN/A
322SN/A/**
332SN/A * @file
342SN/A * Declaration of a bus object.
352SN/A */
361354SN/A
371354SN/A#ifndef __MEM_BUS_HH__
382SN/A#define __MEM_BUS_HH__
392SN/A
405501Snate@binkert.org#include <string>
415546Snate@binkert.org#include <list>
427004Snate@binkert.org#include <inttypes.h>
432SN/A
442SN/A#include "base/range.hh"
455769Snate@binkert.org#include "mem/mem_object.hh"
462361SN/A#include "mem/packet.hh"
471354SN/A#include "mem/port.hh"
486216Snate@binkert.org#include "mem/request.hh"
498232Snate@binkert.org#include "sim/eventq.hh"
5056SN/A
512SN/Aclass Bus : public MemObject
525543Ssaidi@eecs.umich.edu{
532SN/A    /** a globally unique id for this bus. */
541354SN/A    int busId;
551354SN/A    /** the clock speed for the bus */
562SN/A    int clock;
572SN/A    /** the width of the bus in bytes */
582SN/A    int width;
592SN/A    /** the next tick at which the bus will be idle */
605501Snate@binkert.org    Tick tickNextIdle;
615501Snate@binkert.org
622SN/A    Event * drainEvent;
639044SAli.Saidi@ARM.com
642SN/A    static const int defaultId = -3; //Make it unique from Broadcast
652SN/A
662SN/A    struct DevMap {
675769Snate@binkert.org        int portId;
688902Sandreas.hansson@arm.com        Range<Addr> range;
695769Snate@binkert.org    };
705769Snate@binkert.org    std::vector<DevMap> portList;
717059Snate@binkert.org    AddrRangeList defaultRange;
727059Snate@binkert.org    std::vector<DevMap> portSnoopList;
737059Snate@binkert.org
747059Snate@binkert.org    /** Function called by the port when the bus is recieving a Timing
757059Snate@binkert.org      transaction.*/
767059Snate@binkert.org    bool recvTiming(PacketPtr pkt);
777059Snate@binkert.org
787059Snate@binkert.org    /** Function called by the port when the bus is recieving a Atomic
797059Snate@binkert.org      transaction.*/
807059Snate@binkert.org    Tick recvAtomic(PacketPtr pkt);
817059Snate@binkert.org
827059Snate@binkert.org    /** Function called by the port when the bus is recieving a Functional
837059Snate@binkert.org        transaction.*/
847059Snate@binkert.org    void recvFunctional(PacketPtr pkt);
857059Snate@binkert.org
867059Snate@binkert.org    /** Timing function called by port when it is once again able to process
875769Snate@binkert.org     * requests. */
887058Snate@binkert.org    void recvRetry(int id);
897058Snate@binkert.org
907058Snate@binkert.org    /** Function called by the port when the bus is recieving a status change.*/
912SN/A    void recvStatusChange(Port::Status status, int id);
925502Snate@binkert.org
935502Snate@binkert.org    /** Find which port connected to this bus (if any) should be given a packet
945502Snate@binkert.org     * with this address.
955503Snate@binkert.org     * @param addr Address to find port for.
965503Snate@binkert.org     * @param id Id of the port this packet was received from (to prevent
975502Snate@binkert.org     *             loops)
985502Snate@binkert.org     * @return pointer to port that the packet should be sent out of.
995502Snate@binkert.org     */
1005502Snate@binkert.org    Port *findPort(Addr addr, int id);
1015502Snate@binkert.org
1025502Snate@binkert.org    /** Find all ports with a matching snoop range, except src port.  Keep in mind
1035502Snate@binkert.org     * that the ranges shouldn't overlap or you will get a double snoop to the same
1045602Snate@binkert.org     * interface.and the cache will assert out.
1055602Snate@binkert.org     * @param addr Address to find snoop prts for.
1065501Snate@binkert.org     * @param id Id of the src port of the request to avoid calling snoop on src
1075543Ssaidi@eecs.umich.edu     * @return vector of IDs to snoop on
1087058Snate@binkert.org     */
1095769Snate@binkert.org    std::vector<int> findSnoopPorts(Addr addr, int id);
1104016Sstever@eecs.umich.edu
1114016Sstever@eecs.umich.edu    /** Snoop all relevant ports atomicly. */
1124016Sstever@eecs.umich.edu    Tick atomicSnoop(PacketPtr pkt);
1134016Sstever@eecs.umich.edu
1144016Sstever@eecs.umich.edu    /** Snoop all relevant ports functionally. */
1154016Sstever@eecs.umich.edu    void functionalSnoop(PacketPtr pkt);
1164016Sstever@eecs.umich.edu
1174016Sstever@eecs.umich.edu    /** Call snoop on caches, be sure to set SNOOP_COMMIT bit if you want
1184016Sstever@eecs.umich.edu     * the snoop to happen
1195501Snate@binkert.org     * @return True if succeds.
1205605Snate@binkert.org     */
1215605Snate@binkert.org    bool timingSnoop(PacketPtr pkt);
1225605Snate@binkert.org
1235605Snate@binkert.org    /** Process address range request.
1245501Snate@binkert.org     * @param resp addresses that we can respond to
1254016Sstever@eecs.umich.edu     * @param snoop addresses that we would like to snoop
1265577SSteve.Reinhardt@amd.com     * @param id ide of the busport that made the request.
1275501Snate@binkert.org     */
1285501Snate@binkert.org    void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id);
1295501Snate@binkert.org
1305502Snate@binkert.org    /** Occupy the bus with transmitting the packet pkt */
1315502Snate@binkert.org    void occupyBus(PacketPtr pkt);
1325605Snate@binkert.org
1335502Snate@binkert.org    /** Declaration of the buses port type, one will be instantiated for each
1345502Snate@binkert.org        of the interfaces connecting to the bus. */
1355605Snate@binkert.org    class BusPort : public Port
1365605Snate@binkert.org    {
1375605Snate@binkert.org        bool _onRetryList;
1385577SSteve.Reinhardt@amd.com
1397823Ssteve.reinhardt@amd.com        /** A pointer to the bus to which this port belongs. */
1405502Snate@binkert.org        Bus *bus;
1415502Snate@binkert.org
1425502Snate@binkert.org        /** A id to keep track of the intercafe ID this port is connected to. */
1432SN/A        int id;
1445769Snate@binkert.org
1455769Snate@binkert.org      public:
1465769Snate@binkert.org
1475769Snate@binkert.org        /** Constructor for the BusPort.*/
1485769Snate@binkert.org        BusPort(const std::string &_name, Bus *_bus, int _id)
1495769Snate@binkert.org            : Port(_name), _onRetryList(false), bus(_bus), id(_id)
1502SN/A        { }
1518581Ssteve.reinhardt@amd.com
1528581Ssteve.reinhardt@amd.com        bool onRetryList()
1535769Snate@binkert.org        { return _onRetryList; }
1547059Snate@binkert.org
1555769Snate@binkert.org        void onRetryList(bool newVal)
1565769Snate@binkert.org        { _onRetryList = newVal; }
1572SN/A
1585769Snate@binkert.org      protected:
1595769Snate@binkert.org
1605769Snate@binkert.org        /** When reciving a timing request from the peer port (at id),
1615769Snate@binkert.org            pass it to the bus. */
1625769Snate@binkert.org        virtual bool recvTiming(PacketPtr pkt)
1635769Snate@binkert.org        { pkt->setSrc(id); return bus->recvTiming(pkt); }
1645769Snate@binkert.org
1655769Snate@binkert.org        /** When reciving a Atomic requestfrom the peer port (at id),
1665769Snate@binkert.org            pass it to the bus. */
1675769Snate@binkert.org        virtual Tick recvAtomic(PacketPtr pkt)
1685769Snate@binkert.org        { pkt->setSrc(id); return bus->recvAtomic(pkt); }
1695769Snate@binkert.org
1705769Snate@binkert.org        /** When reciving a Functional requestfrom the peer port (at id),
1715769Snate@binkert.org            pass it to the bus. */
1725769Snate@binkert.org        virtual void recvFunctional(PacketPtr pkt)
1735769Snate@binkert.org        { pkt->setSrc(id); bus->recvFunctional(pkt); }
1745769Snate@binkert.org
1755769Snate@binkert.org        /** When reciving a status changefrom the peer port (at id),
1765769Snate@binkert.org            pass it to the bus. */
1775769Snate@binkert.org        virtual void recvStatusChange(Status status)
1785769Snate@binkert.org        { bus->recvStatusChange(status, id); }
1795501Snate@binkert.org
1805543Ssaidi@eecs.umich.edu        /** When reciving a retry from the peer port (at id),
1812SN/A            pass it to the bus. */
1822SN/A        virtual void recvRetry()
183396SN/A        { bus->recvRetry(id); }
184396SN/A
185396SN/A        // This should return all the 'owned' addresses that are
186396SN/A        // downstream from this bus, yes?  That is, the union of all
1875501Snate@binkert.org        // the 'owned' address ranges of all the other interfaces on
1887058Snate@binkert.org        // this bus...
1897058Snate@binkert.org        virtual void getDeviceAddressRanges(AddrRangeList &resp,
1903329Sstever@eecs.umich.edu                                            AddrRangeList &snoop)
1917058Snate@binkert.org        { bus->addressRanges(resp, snoop, id); }
1927058Snate@binkert.org
1937058Snate@binkert.org        // Hack to make translating port work without changes
1947058Snate@binkert.org        virtual int deviceBlockSize() { return 32; }
195396SN/A
1967058Snate@binkert.org    };
1977058Snate@binkert.org
1987058Snate@binkert.org    class BusFreeEvent : public Event
1997058Snate@binkert.org    {
2003329Sstever@eecs.umich.edu        Bus * bus;
2017058Snate@binkert.org
2027058Snate@binkert.org      public:
2037058Snate@binkert.org        BusFreeEvent(Bus * _bus);
2047058Snate@binkert.org        void process();
2057058Snate@binkert.org        const char *description();
206396SN/A    };
2077058Snate@binkert.org
2087058Snate@binkert.org    BusFreeEvent busIdle;
2097058Snate@binkert.org
2107058Snate@binkert.org    bool inRetry;
211396SN/A
2127058Snate@binkert.org    /** An array of pointers to the peer port interfaces
2137058Snate@binkert.org        connected to this bus.*/
214396SN/A    std::vector<BusPort*> interfaces;
2157058Snate@binkert.org
2167058Snate@binkert.org    /** An array of pointers to ports that retry should be called on because the
2177058Snate@binkert.org     * original send failed for whatever reason.*/
2187058Snate@binkert.org    std::list<BusPort*> retryList;
219396SN/A
2207058Snate@binkert.org    void addToRetryList(BusPort * port)
2217058Snate@binkert.org    {
2227058Snate@binkert.org        if (!inRetry) {
223396SN/A            // The device wasn't retrying a packet, or wasn't at an appropriate
2247058Snate@binkert.org            // time.
2257058Snate@binkert.org            assert(!port->onRetryList());
2267058Snate@binkert.org            port->onRetryList(true);
2274075Sbinkertn@umich.edu            retryList.push_back(port);
2287058Snate@binkert.org        } else {
2297058Snate@binkert.org            if (port->onRetryList()) {
2305501Snate@binkert.org                // The device was retrying a packet. It didn't work, so we'll leave
2317058Snate@binkert.org                // it at the head of the retry list.
2327058Snate@binkert.org                assert(port == retryList.front());
2337058Snate@binkert.org                inRetry = false;
2347058Snate@binkert.org            }
2357058Snate@binkert.org            else {
2367058Snate@binkert.org                port->onRetryList(true);
237396SN/A                retryList.push_back(port);
2382SN/A            }
2392SN/A        }
2402SN/A    }
2412SN/A
2428581Ssteve.reinhardt@amd.com    /** Port that handles requests that don't match any of the interfaces.*/
2438581Ssteve.reinhardt@amd.com    BusPort *defaultPort;
2448581Ssteve.reinhardt@amd.com
245224SN/A  public:
2468581Ssteve.reinhardt@amd.com
2474016Sstever@eecs.umich.edu    /** A function used to return the port associated with this bus object. */
2485501Snate@binkert.org    virtual Port *getPort(const std::string &if_name, int idx = -1);
2495605Snate@binkert.org
2505501Snate@binkert.org    virtual void init();
2515501Snate@binkert.org
2527823Ssteve.reinhardt@amd.com    unsigned int drain(Event *de);
2535501Snate@binkert.org
2544016Sstever@eecs.umich.edu    Bus(const std::string &n, int bus_id, int _clock, int _width)
255224SN/A        : MemObject(n), busId(bus_id), clock(_clock), width(_width),
256224SN/A        tickNextIdle(0), busIdle(this), inRetry(false), defaultPort(NULL)
2575768Snate@binkert.org    {
2585768Snate@binkert.org        //Both the width and clock period must be positive
259265SN/A        if (width <= 0)
2605501Snate@binkert.org            fatal("Bus width must be positive\n");
2615501Snate@binkert.org        if (clock <= 0)
2625501Snate@binkert.org            fatal("Bus clock period must be positive\n");
2635501Snate@binkert.org    }
2645501Snate@binkert.org
2655501Snate@binkert.org};
2665501Snate@binkert.org
2675501Snate@binkert.org#endif //__MEM_BUS_HH__
2685501Snate@binkert.org