coherent_xbar.hh revision 8711
19241Sandreas.hansson@arm.com/*
211491Sandreas.hansson@arm.com * Copyright (c) 2011 ARM Limited
39241Sandreas.hansson@arm.com * All rights reserved
49241Sandreas.hansson@arm.com *
59241Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
69241Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
79241Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
89241Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
99241Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
109241Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
119241Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
129241Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
139241Sandreas.hansson@arm.com *
149241Sandreas.hansson@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
159241Sandreas.hansson@arm.com * All rights reserved.
169241Sandreas.hansson@arm.com *
179241Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
189241Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
199241Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
209241Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
219241Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
229241Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
239241Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
249241Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
259241Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
269241Sandreas.hansson@arm.com * this software without specific prior written permission.
279241Sandreas.hansson@arm.com *
289241Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
299241Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
309241Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
319241Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
329241Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
339241Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
349241Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
359241Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
369241Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
379241Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
389241Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
399241Sandreas.hansson@arm.com *
409241Sandreas.hansson@arm.com * Authors: Ron Dreslinski
4111540Sandreas.sandberg@arm.com *          Ali Saidi
4211540Sandreas.sandberg@arm.com */
4311540Sandreas.sandberg@arm.com
4411540Sandreas.sandberg@arm.com/**
459241Sandreas.hansson@arm.com * @file
469241Sandreas.hansson@arm.com * Declaration of a bus object.
479241Sandreas.hansson@arm.com */
4810138Sneha.agarwal@arm.com
499241Sandreas.hansson@arm.com#ifndef __MEM_BUS_HH__
509241Sandreas.hansson@arm.com#define __MEM_BUS_HH__
519241Sandreas.hansson@arm.com
529241Sandreas.hansson@arm.com#include <list>
539241Sandreas.hansson@arm.com#include <set>
549241Sandreas.hansson@arm.com#include <string>
559241Sandreas.hansson@arm.com
569241Sandreas.hansson@arm.com#include "base/hashmap.hh"
579241Sandreas.hansson@arm.com#include "base/range.hh"
589241Sandreas.hansson@arm.com#include "base/range_map.hh"
599241Sandreas.hansson@arm.com#include "base/types.hh"
609241Sandreas.hansson@arm.com#include "mem/mem_object.hh"
619718Sandreas.hansson@arm.com#include "mem/packet.hh"
629720Sandreas.hansson@arm.com#include "mem/port.hh"
6311491Sandreas.hansson@arm.com#include "mem/request.hh"
6411491Sandreas.hansson@arm.com#include "params/Bus.hh"
659717Sandreas.hansson@arm.com#include "sim/eventq.hh"
669719Sandreas.hansson@arm.com
6710360Sandreas.hansson@arm.comclass Bus : public MemObject
689241Sandreas.hansson@arm.com{
699719Sandreas.hansson@arm.com    /** Declaration of the buses port type, one will be instantiated for each
709719Sandreas.hansson@arm.com        of the interfaces connecting to the bus. */
7111393Sandreas.hansson@arm.com    class BusPort : public Port
7211393Sandreas.hansson@arm.com    {
739241Sandreas.hansson@arm.com        bool _onRetryList;
749241Sandreas.hansson@arm.com
759241Sandreas.hansson@arm.com        /** A pointer to the bus to which this port belongs. */
769241Sandreas.hansson@arm.com        Bus *bus;
779241Sandreas.hansson@arm.com
789241Sandreas.hansson@arm.com        /** A id to keep track of the intercafe ID this port is connected to. */
799241Sandreas.hansson@arm.com        int id;
809241Sandreas.hansson@arm.com
819241Sandreas.hansson@arm.com      public:
829294Sandreas.hansson@arm.com
839294Sandreas.hansson@arm.com        /** Constructor for the BusPort.*/
849241Sandreas.hansson@arm.com        BusPort(const std::string &_name, Bus *_bus, int _id)
859241Sandreas.hansson@arm.com            : Port(_name, _bus), _onRetryList(false), bus(_bus), id(_id)
869241Sandreas.hansson@arm.com        { }
879241Sandreas.hansson@arm.com
889241Sandreas.hansson@arm.com        bool onRetryList()
899241Sandreas.hansson@arm.com        { return _onRetryList; }
909241Sandreas.hansson@arm.com
919241Sandreas.hansson@arm.com        void onRetryList(bool newVal)
929241Sandreas.hansson@arm.com        { _onRetryList = newVal; }
939241Sandreas.hansson@arm.com
949241Sandreas.hansson@arm.com        int getId() { return id; }
959241Sandreas.hansson@arm.com
969241Sandreas.hansson@arm.com        /**
979241Sandreas.hansson@arm.com         * Determine if this port should be considered a snooper. This
989241Sandreas.hansson@arm.com         * is determined by the bus.
999524SAndreas.Sandberg@ARM.com         *
1009241Sandreas.hansson@arm.com         * @return a boolean that is true if this port is snooping
1019241Sandreas.hansson@arm.com         */
1029718Sandreas.hansson@arm.com        virtual bool isSnooping()
1039718Sandreas.hansson@arm.com        { return bus->isSnooping(id); }
1049241Sandreas.hansson@arm.com
1059717Sandreas.hansson@arm.com      protected:
1069241Sandreas.hansson@arm.com
1079241Sandreas.hansson@arm.com        /** When reciving a timing request from the peer port (at id),
1089241Sandreas.hansson@arm.com            pass it to the bus. */
1099241Sandreas.hansson@arm.com        virtual bool recvTiming(PacketPtr pkt)
1109241Sandreas.hansson@arm.com        { pkt->setSrc(id); return bus->recvTiming(pkt); }
1119241Sandreas.hansson@arm.com
1129241Sandreas.hansson@arm.com        /** When reciving a Atomic requestfrom the peer port (at id),
1139241Sandreas.hansson@arm.com            pass it to the bus. */
1149241Sandreas.hansson@arm.com        virtual Tick recvAtomic(PacketPtr pkt)
1159241Sandreas.hansson@arm.com        { pkt->setSrc(id); return bus->recvAtomic(pkt); }
1169524SAndreas.Sandberg@ARM.com
1179719Sandreas.hansson@arm.com        /** When reciving a Functional requestfrom the peer port (at id),
1189720Sandreas.hansson@arm.com            pass it to the bus. */
1199719Sandreas.hansson@arm.com        virtual void recvFunctional(PacketPtr pkt)
1209241Sandreas.hansson@arm.com        { pkt->setSrc(id); bus->recvFunctional(pkt); }
1219241Sandreas.hansson@arm.com
1229241Sandreas.hansson@arm.com        /** When reciving a range change from the peer port (at id),
1239241Sandreas.hansson@arm.com            pass it to the bus. */
1249241Sandreas.hansson@arm.com        virtual void recvRangeChange()
1259241Sandreas.hansson@arm.com        { bus->recvRangeChange(id); }
12610913Sandreas.sandberg@arm.com
12710913Sandreas.sandberg@arm.com        /** When reciving a retry from the peer port (at id),
1289241Sandreas.hansson@arm.com            pass it to the bus. */
12910051Srioshering@gmail.com        virtual void recvRetry()
13010051Srioshering@gmail.com        { bus->recvRetry(id); }
13110913Sandreas.sandberg@arm.com
13210051Srioshering@gmail.com        // This should return all the 'owned' addresses that are
13310051Srioshering@gmail.com        // downstream from this bus, yes?  That is, the union of all
1349719Sandreas.hansson@arm.com        // the 'owned' address ranges of all the other interfaces on
1359719Sandreas.hansson@arm.com        // this bus...
1369719Sandreas.hansson@arm.com        virtual AddrRangeList getAddrRanges()
1379719Sandreas.hansson@arm.com        { return bus->getAddrRanges(id); }
1389719Sandreas.hansson@arm.com
13910913Sandreas.sandberg@arm.com        // Ask the bus to ask everyone on the bus what their block size is and
1409719Sandreas.hansson@arm.com        // take the max of it. This might need to be changed a bit if we ever
14110913Sandreas.sandberg@arm.com        // support multiple block sizes.
1429719Sandreas.hansson@arm.com        virtual unsigned deviceBlockSize() const
1439241Sandreas.hansson@arm.com        { return bus->findBlockSize(id); }
1449241Sandreas.hansson@arm.com
1459241Sandreas.hansson@arm.com    };
14610905Sandreas.sandberg@arm.com
1479241Sandreas.hansson@arm.com    class BusFreeEvent : public Event
1489241Sandreas.hansson@arm.com    {
1499241Sandreas.hansson@arm.com        Bus * bus;
1509241Sandreas.hansson@arm.com
1519719Sandreas.hansson@arm.com      public:
1529241Sandreas.hansson@arm.com        BusFreeEvent(Bus * _bus);
1539719Sandreas.hansson@arm.com        void process();
1549241Sandreas.hansson@arm.com        const char *description() const;
1559717Sandreas.hansson@arm.com    };
1569241Sandreas.hansson@arm.com
1579241Sandreas.hansson@arm.com    /** a globally unique id for this bus. */
1589241Sandreas.hansson@arm.com    int busId;
1599719Sandreas.hansson@arm.com    /** the clock speed for the bus */
1609719Sandreas.hansson@arm.com    int clock;
1619719Sandreas.hansson@arm.com    /** cycles of overhead per transaction */
1629241Sandreas.hansson@arm.com    int headerCycles;
1639241Sandreas.hansson@arm.com    /** the width of the bus in bytes */
1649241Sandreas.hansson@arm.com    int width;
16510905Sandreas.sandberg@arm.com    /** the next tick at which the bus will be idle */
1669241Sandreas.hansson@arm.com    Tick tickNextIdle;
1679241Sandreas.hansson@arm.com
1689717Sandreas.hansson@arm.com    Event * drainEvent;
1699717Sandreas.hansson@arm.com
1709717Sandreas.hansson@arm.com
1719717Sandreas.hansson@arm.com    static const int defaultId = -3; //Make it unique from Broadcast
1729241Sandreas.hansson@arm.com
1739241Sandreas.hansson@arm.com    typedef range_map<Addr,int>::iterator PortIter;
1749241Sandreas.hansson@arm.com    range_map<Addr, int> portMap;
1759719Sandreas.hansson@arm.com
1769719Sandreas.hansson@arm.com    AddrRangeList defaultRange;
1779719Sandreas.hansson@arm.com
1789719Sandreas.hansson@arm.com    typedef std::vector<BusPort*>::iterator SnoopIter;
1799719Sandreas.hansson@arm.com    std::vector<BusPort*> snoopPorts;
1809720Sandreas.hansson@arm.com
1819719Sandreas.hansson@arm.com    /** Function called by the port when the bus is recieving a Timing
1829241Sandreas.hansson@arm.com      transaction.*/
1839241Sandreas.hansson@arm.com    bool recvTiming(PacketPtr pkt);
1849241Sandreas.hansson@arm.com
1859717Sandreas.hansson@arm.com    /** Function called by the port when the bus is recieving a Atomic
1869241Sandreas.hansson@arm.com      transaction.*/
18711491Sandreas.hansson@arm.com    Tick recvAtomic(PacketPtr pkt);
18811491Sandreas.hansson@arm.com
18911491Sandreas.hansson@arm.com    /** Function called by the port when the bus is recieving a Functional
1909717Sandreas.hansson@arm.com        transaction.*/
1919717Sandreas.hansson@arm.com    void recvFunctional(PacketPtr pkt);
1929717Sandreas.hansson@arm.com
1939717Sandreas.hansson@arm.com    /** Timing function called by port when it is once again able to process
1949717Sandreas.hansson@arm.com     * requests. */
1959719Sandreas.hansson@arm.com    void recvRetry(int id);
1969719Sandreas.hansson@arm.com
1979718Sandreas.hansson@arm.com    /** Function called by the port when the bus is recieving a range change.*/
19810266Sandreas.hansson@arm.com    void recvRangeChange(int id);
19910266Sandreas.hansson@arm.com
20010266Sandreas.hansson@arm.com    /** Find which port connected to this bus (if any) should be given a packet
20110266Sandreas.hansson@arm.com     * with this address.
20210266Sandreas.hansson@arm.com     * @param addr Address to find port for.
20310266Sandreas.hansson@arm.com     * @return id of port that the packet should be sent out of.
20410266Sandreas.hansson@arm.com     */
20510266Sandreas.hansson@arm.com    int findPort(Addr addr);
20610266Sandreas.hansson@arm.com
20710266Sandreas.hansson@arm.com    // Cache for the findPort function storing recently used ports from portMap
20810266Sandreas.hansson@arm.com    struct PortCache {
20910266Sandreas.hansson@arm.com        bool valid;
21011393Sandreas.hansson@arm.com        int  id;
21111393Sandreas.hansson@arm.com        Addr start;
21211393Sandreas.hansson@arm.com        Addr end;
21311393Sandreas.hansson@arm.com    };
21411393Sandreas.hansson@arm.com
21511393Sandreas.hansson@arm.com    PortCache portCache[3];
21611222Sandreas.hansson@arm.com
21711222Sandreas.hansson@arm.com    // Checks the cache and returns the id of the port that has the requested
21811222Sandreas.hansson@arm.com    // address within its range
2199719Sandreas.hansson@arm.com    inline int checkPortCache(Addr addr) {
2209719Sandreas.hansson@arm.com        if (portCache[0].valid && addr >= portCache[0].start &&
2219719Sandreas.hansson@arm.com            addr < portCache[0].end) {
2229719Sandreas.hansson@arm.com            return portCache[0].id;
2239719Sandreas.hansson@arm.com        }
2249719Sandreas.hansson@arm.com        if (portCache[1].valid && addr >= portCache[1].start &&
2259719Sandreas.hansson@arm.com                   addr < portCache[1].end) {
2269719Sandreas.hansson@arm.com            return portCache[1].id;
2279719Sandreas.hansson@arm.com        }
2289720Sandreas.hansson@arm.com        if (portCache[2].valid && addr >= portCache[2].start &&
2299719Sandreas.hansson@arm.com            addr < portCache[2].end) {
2309719Sandreas.hansson@arm.com            return portCache[2].id;
2319719Sandreas.hansson@arm.com        }
2329717Sandreas.hansson@arm.com
2339241Sandreas.hansson@arm.com        return -1;
2349241Sandreas.hansson@arm.com    }
23511540Sandreas.sandberg@arm.com
23611540Sandreas.sandberg@arm.com    // Clears the earliest entry of the cache and inserts a new port entry
23711540Sandreas.sandberg@arm.com    inline void updatePortCache(short id, Addr start, Addr end) {
23811540Sandreas.sandberg@arm.com        portCache[2].valid = portCache[1].valid;
23911540Sandreas.sandberg@arm.com        portCache[2].id    = portCache[1].id;
24011540Sandreas.sandberg@arm.com        portCache[2].start = portCache[1].start;
24111540Sandreas.sandberg@arm.com        portCache[2].end   = portCache[1].end;
24211540Sandreas.sandberg@arm.com
24311540Sandreas.sandberg@arm.com        portCache[1].valid = portCache[0].valid;
24411540Sandreas.sandberg@arm.com        portCache[1].id    = portCache[0].id;
24511540Sandreas.sandberg@arm.com        portCache[1].start = portCache[0].start;
24611540Sandreas.sandberg@arm.com        portCache[1].end   = portCache[0].end;
24711540Sandreas.sandberg@arm.com
24811540Sandreas.sandberg@arm.com        portCache[0].valid = true;
24911540Sandreas.sandberg@arm.com        portCache[0].id    = id;
25011540Sandreas.sandberg@arm.com        portCache[0].start = start;
25111540Sandreas.sandberg@arm.com        portCache[0].end   = end;
25211540Sandreas.sandberg@arm.com    }
25311540Sandreas.sandberg@arm.com
25411540Sandreas.sandberg@arm.com    // Clears the cache. Needs to be called in constructor.
25511540Sandreas.sandberg@arm.com    inline void clearPortCache() {
2569241Sandreas.hansson@arm.com        portCache[2].valid = false;
2579718Sandreas.hansson@arm.com        portCache[1].valid = false;
2589241Sandreas.hansson@arm.com        portCache[0].valid = false;
2599241Sandreas.hansson@arm.com    }
2609241Sandreas.hansson@arm.com
2619241Sandreas.hansson@arm.com    /**
2629241Sandreas.hansson@arm.com     * Return the address ranges this port is responsible for.
2639241Sandreas.hansson@arm.com     *
2649241Sandreas.hansson@arm.com     * @param id id of the bus port that made the request
2659718Sandreas.hansson@arm.com     *
2669241Sandreas.hansson@arm.com     * @return a list of non-overlapping address ranges
2679241Sandreas.hansson@arm.com     */
2689718Sandreas.hansson@arm.com    AddrRangeList getAddrRanges(int id);
2699241Sandreas.hansson@arm.com
2709241Sandreas.hansson@arm.com    /**
27110128Sstan.czerniawski@arm.com     * Determine if the bus port is snooping or not.
27210128Sstan.czerniawski@arm.com     *
2739241Sandreas.hansson@arm.com     * @param id id of the bus port that made the request
2749241Sandreas.hansson@arm.com     *
2759241Sandreas.hansson@arm.com     * @return a boolean indicating if this port is snooping or not
2769241Sandreas.hansson@arm.com     */
2779241Sandreas.hansson@arm.com    bool isSnooping(int id);
2789241Sandreas.hansson@arm.com
2799241Sandreas.hansson@arm.com    /** Calculate the timing parameters for the packet.  Updates the
2809241Sandreas.hansson@arm.com     * firstWordTime and finishTime fields of the packet object.
2819241Sandreas.hansson@arm.com     * Returns the tick at which the packet header is completed (which
2829241Sandreas.hansson@arm.com     * will be all that is sent if the target rejects the packet).
2839241Sandreas.hansson@arm.com     */
2849241Sandreas.hansson@arm.com    Tick calcPacketTiming(PacketPtr pkt);
2859241Sandreas.hansson@arm.com
2869241Sandreas.hansson@arm.com    /** Occupy the bus until until */
2879241Sandreas.hansson@arm.com    void occupyBus(Tick until);
2889241Sandreas.hansson@arm.com
2899241Sandreas.hansson@arm.com    /** Ask everyone on the bus what their size is
2909241Sandreas.hansson@arm.com     * @param id id of the busport that made the request
2919241Sandreas.hansson@arm.com     * @return the max of all the sizes
2929241Sandreas.hansson@arm.com     */
2939241Sandreas.hansson@arm.com    unsigned findBlockSize(int id);
2949241Sandreas.hansson@arm.com
2959241Sandreas.hansson@arm.com    BusFreeEvent busIdle;
2969241Sandreas.hansson@arm.com
2979241Sandreas.hansson@arm.com    bool inRetry;
2989241Sandreas.hansson@arm.com    std::set<int> inRecvRangeChange;
2999241Sandreas.hansson@arm.com
30011540Sandreas.sandberg@arm.com    /** max number of bus ids we've handed out so far */
3019241Sandreas.hansson@arm.com    short maxId;
3029718Sandreas.hansson@arm.com
3039241Sandreas.hansson@arm.com    /** An array of pointers to the peer port interfaces
3049241Sandreas.hansson@arm.com        connected to this bus.*/
3059241Sandreas.hansson@arm.com    m5::hash_map<short,BusPort*> interfaces;
3069718Sandreas.hansson@arm.com
3079241Sandreas.hansson@arm.com    /** An array of pointers to ports that retry should be called on because the
30810138Sneha.agarwal@arm.com     * original send failed for whatever reason.*/
30910392Swendy.elsasser@arm.com    std::list<BusPort*> retryList;
3109241Sandreas.hansson@arm.com
3119241Sandreas.hansson@arm.com    void addToRetryList(BusPort * port)
3129241Sandreas.hansson@arm.com    {
3139241Sandreas.hansson@arm.com        if (!inRetry) {
3149241Sandreas.hansson@arm.com            // The device wasn't retrying a packet, or wasn't at an appropriate
3159241Sandreas.hansson@arm.com            // time.
3169241Sandreas.hansson@arm.com            assert(!port->onRetryList());
3179241Sandreas.hansson@arm.com            port->onRetryList(true);
3189241Sandreas.hansson@arm.com            retryList.push_back(port);
3199241Sandreas.hansson@arm.com        } else {
3209241Sandreas.hansson@arm.com            if (port->onRetryList()) {
3219241Sandreas.hansson@arm.com                // The device was retrying a packet. It didn't work, so we'll leave
3229241Sandreas.hansson@arm.com                // it at the head of the retry list.
3239241Sandreas.hansson@arm.com                assert(port == retryList.front());
3249241Sandreas.hansson@arm.com                inRetry = false;
3259241Sandreas.hansson@arm.com            }
3269718Sandreas.hansson@arm.com            else {
3279814Sandreas.hansson@arm.com                port->onRetryList(true);
3289718Sandreas.hansson@arm.com                retryList.push_back(port);
32910138Sneha.agarwal@arm.com            }
3309814Sandreas.hansson@arm.com        }
3319718Sandreas.hansson@arm.com    }
3329241Sandreas.hansson@arm.com
3339718Sandreas.hansson@arm.com    /** Port that handles requests that don't match any of the interfaces.*/
3349241Sandreas.hansson@arm.com    BusPort *defaultPort;
3359722Ssascha.bischoff@arm.com
3369722Ssascha.bischoff@arm.com    BusPort *funcPort;
3379722Ssascha.bischoff@arm.com    int funcPortId;
3389241Sandreas.hansson@arm.com
3399718Sandreas.hansson@arm.com    /** If true, use address range provided by default device.  Any
3409241Sandreas.hansson@arm.com       address not handled by another port and not in default device's
3419241Sandreas.hansson@arm.com       range will cause a fatal error.  If false, just send all
3429241Sandreas.hansson@arm.com       addresses not handled by another port to default device. */
3439241Sandreas.hansson@arm.com    bool useDefaultRange;
3449241Sandreas.hansson@arm.com
3459241Sandreas.hansson@arm.com    unsigned defaultBlockSize;
3469718Sandreas.hansson@arm.com    unsigned cachedBlockSize;
3479241Sandreas.hansson@arm.com    bool cachedBlockSizeValid;
3489241Sandreas.hansson@arm.com
3499241Sandreas.hansson@arm.com   // Cache for the peer port interfaces
3509241Sandreas.hansson@arm.com    struct BusCache {
3519241Sandreas.hansson@arm.com        bool  valid;
35210392Swendy.elsasser@arm.com        short id;
35310138Sneha.agarwal@arm.com        BusPort  *port;
35410138Sneha.agarwal@arm.com    };
35510138Sneha.agarwal@arm.com
35610138Sneha.agarwal@arm.com    BusCache busCache[3];
35710138Sneha.agarwal@arm.com
35810138Sneha.agarwal@arm.com    // Checks the peer port interfaces cache for the port id and returns
35910138Sneha.agarwal@arm.com    // a pointer to the matching port
36010392Swendy.elsasser@arm.com    inline BusPort* checkBusCache(short id) {
36110138Sneha.agarwal@arm.com        if (busCache[0].valid && id == busCache[0].id) {
36210138Sneha.agarwal@arm.com            return busCache[0].port;
36310392Swendy.elsasser@arm.com        }
36410392Swendy.elsasser@arm.com        if (busCache[1].valid && id == busCache[1].id) {
36510138Sneha.agarwal@arm.com            return busCache[1].port;
36610138Sneha.agarwal@arm.com        }
36710138Sneha.agarwal@arm.com        if (busCache[2].valid && id == busCache[2].id) {
36810138Sneha.agarwal@arm.com            return busCache[2].port;
36910138Sneha.agarwal@arm.com        }
37010138Sneha.agarwal@arm.com
37110138Sneha.agarwal@arm.com        return NULL;
37210746Swendy.elsasser@arm.com    }
37310746Swendy.elsasser@arm.com
37410138Sneha.agarwal@arm.com    // Replaces the earliest entry in the cache with a new entry
37510138Sneha.agarwal@arm.com    inline void updateBusCache(short id, BusPort *port) {
37610138Sneha.agarwal@arm.com        busCache[2].valid = busCache[1].valid;
37710138Sneha.agarwal@arm.com        busCache[2].id    = busCache[1].id;
37810138Sneha.agarwal@arm.com        busCache[2].port  = busCache[1].port;
37910138Sneha.agarwal@arm.com
38010138Sneha.agarwal@arm.com        busCache[1].valid = busCache[0].valid;
38110138Sneha.agarwal@arm.com        busCache[1].id    = busCache[0].id;
38210138Sneha.agarwal@arm.com        busCache[1].port  = busCache[0].port;
38310138Sneha.agarwal@arm.com
38410138Sneha.agarwal@arm.com        busCache[0].valid = true;
38510138Sneha.agarwal@arm.com        busCache[0].id    = id;
38610138Sneha.agarwal@arm.com        busCache[0].port  = port;
38710392Swendy.elsasser@arm.com    }
38810392Swendy.elsasser@arm.com
38910392Swendy.elsasser@arm.com    // Invalidates the cache. Needs to be called in constructor.
39010392Swendy.elsasser@arm.com    inline void clearBusCache() {
39110392Swendy.elsasser@arm.com        busCache[2].valid = false;
39210392Swendy.elsasser@arm.com        busCache[1].valid = false;
39310392Swendy.elsasser@arm.com        busCache[0].valid = false;
39410392Swendy.elsasser@arm.com    }
39510392Swendy.elsasser@arm.com
39610392Swendy.elsasser@arm.com
39710392Swendy.elsasser@arm.com  public:
39810392Swendy.elsasser@arm.com
39910392Swendy.elsasser@arm.com    /** A function used to return the port associated with this bus object. */
40010392Swendy.elsasser@arm.com    virtual Port *getPort(const std::string &if_name, int idx = -1);
40110392Swendy.elsasser@arm.com
40210392Swendy.elsasser@arm.com    virtual void init();
40310392Swendy.elsasser@arm.com    virtual void startup();
40410392Swendy.elsasser@arm.com
40510392Swendy.elsasser@arm.com    unsigned int drain(Event *de);
40610392Swendy.elsasser@arm.com
40710392Swendy.elsasser@arm.com    Bus(const BusParams *p);
40810392Swendy.elsasser@arm.com};
40910392Swendy.elsasser@arm.com
41010392Swendy.elsasser@arm.com#endif //__MEM_BUS_HH__
41110392Swendy.elsasser@arm.com