xbar.hh revision 10405
12381SN/A/*
210405Sandreas.hansson@arm.com * Copyright (c) 2011-2014 ARM Limited
38711SN/A * All rights reserved
48711SN/A *
58711SN/A * The license below extends only to copyright in the software and shall
68711SN/A * not be construed as granting a license to any other intellectual
78711SN/A * property including but not limited to intellectual property relating
88711SN/A * to a hardware implementation of the functionality of the software
98711SN/A * licensed hereunder.  You may use the software subject to the license
108711SN/A * terms below provided that you ensure that this notice is replicated
118711SN/A * unmodified and in its entirety in all distributions of the software,
128711SN/A * modified or unmodified, in source code or in binary form.
138711SN/A *
142381SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
152381SN/A * All rights reserved.
162381SN/A *
172381SN/A * Redistribution and use in source and binary forms, with or without
182381SN/A * modification, are permitted provided that the following conditions are
192381SN/A * met: redistributions of source code must retain the above copyright
202381SN/A * notice, this list of conditions and the following disclaimer;
212381SN/A * redistributions in binary form must reproduce the above copyright
222381SN/A * notice, this list of conditions and the following disclaimer in the
232381SN/A * documentation and/or other materials provided with the distribution;
242381SN/A * neither the name of the copyright holders nor the names of its
252381SN/A * contributors may be used to endorse or promote products derived from
262381SN/A * this software without specific prior written permission.
272381SN/A *
282381SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292381SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302381SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312381SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322381SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332381SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342381SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352381SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362381SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372381SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382381SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392665SN/A *
402665SN/A * Authors: Ron Dreslinski
412772SN/A *          Ali Saidi
428715SN/A *          Andreas Hansson
438922SN/A *          William Wang
442381SN/A */
452381SN/A
462381SN/A/**
472982SN/A * @file
4810405Sandreas.hansson@arm.com * Declaration of an abstract crossbar base class.
492381SN/A */
502381SN/A
5110405Sandreas.hansson@arm.com#ifndef __MEM_XBAR_HH__
5210405Sandreas.hansson@arm.com#define __MEM_XBAR_HH__
532381SN/A
549291SN/A#include <deque>
552381SN/A
569235SN/A#include "base/addr_range_map.hh"
576215SN/A#include "base/types.hh"
582381SN/A#include "mem/mem_object.hh"
5910405Sandreas.hansson@arm.com#include "params/BaseXBar.hh"
609712SN/A#include "sim/stats.hh"
612381SN/A
629036SN/A/**
6310405Sandreas.hansson@arm.com * The base crossbar contains the common elements of the non-coherent
6410405Sandreas.hansson@arm.com * and coherent crossbar. It is an abstract class that does not have
6510405Sandreas.hansson@arm.com * any of the functionality relating to the actual reception and
6610405Sandreas.hansson@arm.com * transmission of packets, as this is left for the subclasses.
679036SN/A *
6810405Sandreas.hansson@arm.com * The BaseXBar is responsible for the basic flow control (busy or
699036SN/A * not), the administration of retries, and the address decoding.
709036SN/A */
7110405Sandreas.hansson@arm.comclass BaseXBar : public MemObject
722381SN/A{
739031SN/A
749036SN/A  protected:
752381SN/A
769091SN/A    /**
7710405Sandreas.hansson@arm.com     * A layer is an internal crossbar arbitration point with its own
7810405Sandreas.hansson@arm.com     * flow control. Each layer is a converging multiplexer tree. By
7910405Sandreas.hansson@arm.com     * instantiating one layer per destination port (and per packet
8010405Sandreas.hansson@arm.com     * type, i.e. request, response, snoop request and snoop
8110405Sandreas.hansson@arm.com     * response), we model full crossbar structures like AXI, ACE,
8210405Sandreas.hansson@arm.com     * PCIe, etc.
839093SN/A     *
849093SN/A     * The template parameter, PortClass, indicates the destination
8510405Sandreas.hansson@arm.com     * port type for the layer. The retry list holds either master
8610405Sandreas.hansson@arm.com     * ports or slave ports, depending on the direction of the
8710405Sandreas.hansson@arm.com     * layer. Thus, a request layer has a retry list containing slave
8810405Sandreas.hansson@arm.com     * ports, whereas a response layer holds master ports.
899091SN/A     */
909715SN/A    template <typename SrcType, typename DstType>
919342SN/A    class Layer : public Drainable
929092SN/A    {
939091SN/A
949092SN/A      public:
959092SN/A
969092SN/A        /**
9710405Sandreas.hansson@arm.com         * Create a layer and give it a name. The layer uses
9810405Sandreas.hansson@arm.com         * the crossbar an event manager.
999092SN/A         *
1009715SN/A         * @param _port destination port the layer converges at
10110405Sandreas.hansson@arm.com         * @param _xbar the crossbar this layer belongs to
1029092SN/A         * @param _name the layer's name
1039092SN/A         */
10410405Sandreas.hansson@arm.com        Layer(DstType& _port, BaseXBar& _xbar, const std::string& _name);
1059092SN/A
1069092SN/A        /**
10710405Sandreas.hansson@arm.com         * Drain according to the normal semantics, so that the crossbar
1089092SN/A         * can tell the layer to drain, and pass an event to signal
1099092SN/A         * back when drained.
1109092SN/A         *
1119092SN/A         * @param de drain event to call once drained
1129092SN/A         *
1139092SN/A         * @return 1 if busy or waiting to retry, or 0 if idle
1149092SN/A         */
1159342SN/A        unsigned int drain(DrainManager *dm);
1169092SN/A
1179092SN/A        /**
11810405Sandreas.hansson@arm.com         * Get the crossbar layer's name
1199092SN/A         */
12010405Sandreas.hansson@arm.com        const std::string name() const { return xbar.name() + _name; }
1219092SN/A
1229092SN/A
1239092SN/A        /**
12410405Sandreas.hansson@arm.com         * Determine if the layer accepts a packet from a specific
1259092SN/A         * port. If not, the port in question is also added to the
1269612SN/A         * retry list. In either case the state of the layer is
1279714SN/A         * updated accordingly.
1289092SN/A         *
1299612SN/A         * @param port Source port presenting the packet
1309092SN/A         *
13110405Sandreas.hansson@arm.com         * @return True if the layer accepts the packet
1329092SN/A         */
1339715SN/A        bool tryTiming(SrcType* src_port);
1349092SN/A
1359092SN/A        /**
1369092SN/A         * Deal with a destination port accepting a packet by potentially
1379092SN/A         * removing the source port from the retry list (if retrying) and
13810405Sandreas.hansson@arm.com         * occupying the layer accordingly.
1399092SN/A         *
1409092SN/A         * @param busy_time Time to spend as a result of a successful send
1419092SN/A         */
1429092SN/A        void succeededTiming(Tick busy_time);
1439092SN/A
1449092SN/A        /**
1459092SN/A         * Deal with a destination port not accepting a packet by
1469092SN/A         * potentially adding the source port to the retry list (if
14710405Sandreas.hansson@arm.com         * not already at the front) and occupying the layer
1489092SN/A         * accordingly.
1499092SN/A         *
1509612SN/A         * @param src_port Source port
1519092SN/A         * @param busy_time Time to spend as a result of a failed send
1529092SN/A         */
1539715SN/A        void failedTiming(SrcType* src_port, Tick busy_time);
1549092SN/A
15510405Sandreas.hansson@arm.com        /** Occupy the layer until until */
1569092SN/A        void occupyLayer(Tick until);
1579092SN/A
1589092SN/A        /**
1599612SN/A         * Send a retry to the port at the head of waitingForLayer. The
1609092SN/A         * caller must ensure that the list is not empty.
1619092SN/A         */
1629092SN/A        void retryWaiting();
1639092SN/A
1649092SN/A        /**
1659612SN/A         * Handle a retry from a neighbouring module. This wraps
1669092SN/A         * retryWaiting by verifying that there are ports waiting
1679092SN/A         * before calling retryWaiting.
1689092SN/A         */
1699715SN/A        void recvRetry();
1709092SN/A
1719712SN/A        /**
1729712SN/A         * Register stats for the layer
1739712SN/A         */
1749712SN/A        void regStats();
1759712SN/A
1769092SN/A      private:
1779092SN/A
1789715SN/A        /** The destination port this layer converges at. */
1799715SN/A        DstType& port;
1809715SN/A
18110405Sandreas.hansson@arm.com        /** The crossbar this layer is a part of. */
18210405Sandreas.hansson@arm.com        BaseXBar& xbar;
1839092SN/A
1849092SN/A        /** A name for this layer. */
1859092SN/A        std::string _name;
1869092SN/A
1879092SN/A        /**
18810405Sandreas.hansson@arm.com         * We declare an enum to track the state of the layer. The
18910405Sandreas.hansson@arm.com         * starting point is an idle state where the layer is waiting
19010405Sandreas.hansson@arm.com         * for a packet to arrive. Upon arrival, the layer
1919092SN/A         * transitions to the busy state, where it remains either
1929092SN/A         * until the packet transfer is done, or the header time is
19310405Sandreas.hansson@arm.com         * spent. Once the layer leaves the busy state, it can
1949092SN/A         * either go back to idle, if no packets have arrived while it
19510405Sandreas.hansson@arm.com         * was busy, or the layer goes on to retry the first port
1969612SN/A         * in waitingForLayer. A similar transition takes place from
19710405Sandreas.hansson@arm.com         * idle to retry if the layer receives a retry from one of
1989092SN/A         * its connected ports. The retry state lasts until the port
1999092SN/A         * in questions calls sendTiming and returns control to the
20010405Sandreas.hansson@arm.com         * layer, or goes to a busy state if the port does not
2019092SN/A         * immediately react to the retry by calling sendTiming.
2029092SN/A         */
2039092SN/A        enum State { IDLE, BUSY, RETRY };
2049092SN/A
20510405Sandreas.hansson@arm.com        /** track the state of the layer */
2069092SN/A        State state;
2079092SN/A
2089342SN/A        /** manager to signal when drained */
2099342SN/A        DrainManager *drainManager;
2109092SN/A
2119092SN/A        /**
2129612SN/A         * A deque of ports that retry should be called on because
2139612SN/A         * the original send was delayed due to a busy layer.
2149092SN/A         */
2159715SN/A        std::deque<SrcType*> waitingForLayer;
2169092SN/A
2179092SN/A        /**
2189715SN/A         * Track who is waiting for the retry when receiving it from a
2199715SN/A         * peer. If no port is waiting NULL is stored.
2209612SN/A         */
2219715SN/A        SrcType* waitingForPeer;
2229612SN/A
2239612SN/A        /**
22410405Sandreas.hansson@arm.com         * Release the layer after being occupied and return to an
2259092SN/A         * idle state where we proceed to send a retry to any
2269092SN/A         * potential waiting port, or drain if asked to do so.
2279092SN/A         */
2289092SN/A        void releaseLayer();
2299092SN/A
2309092SN/A        /** event used to schedule a release of the layer */
2319092SN/A        EventWrapper<Layer, &Layer::releaseLayer> releaseEvent;
2329092SN/A
2339712SN/A        /**
2349712SN/A         * Stats for occupancy and utilization. These stats capture
23510405Sandreas.hansson@arm.com         * the time the layer spends in the busy state and are thus only
2369712SN/A         * relevant when the memory system is in timing mode.
2379712SN/A         */
2389712SN/A        Stats::Scalar occupancy;
2399712SN/A        Stats::Formula utilization;
2409712SN/A
2419092SN/A    };
2429091SN/A
2435354SN/A    /** cycles of overhead per transaction */
2449240SN/A    const Cycles headerCycles;
24510405Sandreas.hansson@arm.com    /** the width of the xbar in bytes */
2469240SN/A    const uint32_t width;
2474475SN/A
2489235SN/A    AddrRangeMap<PortID> portMap;
2494475SN/A
25010405Sandreas.hansson@arm.com    /** all contigous ranges seen by this crossbar */
25110405Sandreas.hansson@arm.com    AddrRangeList xbarRanges;
2529564SN/A
2539279SN/A    AddrRange defaultRange;
2544475SN/A
2558948SN/A    /**
25610405Sandreas.hansson@arm.com     * Function called by the port when the crossbar is recieving a
25710405Sandreas.hansson@arm.com     * range change.
2589032SN/A     *
2599032SN/A     * @param master_port_id id of the port that received the change
2609032SN/A     */
2619032SN/A    void recvRangeChange(PortID master_port_id);
2624475SN/A
26310405Sandreas.hansson@arm.com    /** Find which port connected to this crossbar (if any) should be
26410405Sandreas.hansson@arm.com     * given a packet with this address.
26510405Sandreas.hansson@arm.com     *
2664475SN/A     * @param addr Address to find port for.
2674894SN/A     * @return id of port that the packet should be sent out of.
2684475SN/A     */
2699031SN/A    PortID findPort(Addr addr);
2704475SN/A
2714958SN/A    // Cache for the findPort function storing recently used ports from portMap
2724958SN/A    struct PortCache {
2734958SN/A        bool valid;
2749031SN/A        PortID id;
2759279SN/A        AddrRange range;
2764958SN/A    };
2774958SN/A
2784958SN/A    PortCache portCache[3];
2794958SN/A
2804958SN/A    // Checks the cache and returns the id of the port that has the requested
2814958SN/A    // address within its range
2829279SN/A    inline PortID checkPortCache(Addr addr) const {
2839405SN/A        if (portCache[0].valid && portCache[0].range.contains(addr)) {
2844963SN/A            return portCache[0].id;
2854963SN/A        }
2869405SN/A        if (portCache[1].valid && portCache[1].range.contains(addr)) {
2874963SN/A            return portCache[1].id;
2884963SN/A        }
2899405SN/A        if (portCache[2].valid && portCache[2].range.contains(addr)) {
2904963SN/A            return portCache[2].id;
2914958SN/A        }
2924958SN/A
2939031SN/A        return InvalidPortID;
2944958SN/A    }
2954958SN/A
2964958SN/A    // Clears the earliest entry of the cache and inserts a new port entry
2979279SN/A    inline void updatePortCache(short id, const AddrRange& range) {
2984958SN/A        portCache[2].valid = portCache[1].valid;
2994958SN/A        portCache[2].id    = portCache[1].id;
3009279SN/A        portCache[2].range = portCache[1].range;
3014958SN/A
3024958SN/A        portCache[1].valid = portCache[0].valid;
3034958SN/A        portCache[1].id    = portCache[0].id;
3049279SN/A        portCache[1].range = portCache[0].range;
3054958SN/A
3064958SN/A        portCache[0].valid = true;
3074958SN/A        portCache[0].id    = id;
3089279SN/A        portCache[0].range = range;
3094958SN/A    }
3104958SN/A
3114958SN/A    // Clears the cache. Needs to be called in constructor.
3124958SN/A    inline void clearPortCache() {
3134958SN/A        portCache[2].valid = false;
3144958SN/A        portCache[1].valid = false;
3154958SN/A        portCache[0].valid = false;
3164958SN/A    }
3174958SN/A
3188711SN/A    /**
31910405Sandreas.hansson@arm.com     * Return the address ranges the crossbar is responsible for.
3208711SN/A     *
3218711SN/A     * @return a list of non-overlapping address ranges
3224475SN/A     */
3239090SN/A    AddrRangeList getAddrRanges() const;
3248711SN/A
3259547SN/A    /**
3269547SN/A     * Calculate the timing parameters for the packet. Updates the
32710405Sandreas.hansson@arm.com     * firstWordDelay and lastWordDelay fields of the packet
3289547SN/A     * object with the relative number of ticks required to transmit
3299547SN/A     * the header and the first word, and the last word, respectively.
3305354SN/A     */
3319547SN/A    void calcPacketTiming(PacketPtr pkt);
3325354SN/A
3339032SN/A    /**
33410405Sandreas.hansson@arm.com     * Remember for each of the master ports of the crossbar if we got
33510405Sandreas.hansson@arm.com     * an address range from the connected slave. For convenience,
33610405Sandreas.hansson@arm.com     * also keep track of if we got ranges from all the slave modules
33710405Sandreas.hansson@arm.com     * or not.
3389279SN/A     */
3399279SN/A    std::vector<bool> gotAddrRanges;
3409279SN/A    bool gotAllAddrRanges;
3413159SN/A
34210405Sandreas.hansson@arm.com    /** The master and slave ports of the crossbar */
3438966SN/A    std::vector<SlavePort*> slavePorts;
3448966SN/A    std::vector<MasterPort*> masterPorts;
3458966SN/A
3462846SN/A    /** Port that handles requests that don't match any of the interfaces.*/
3479031SN/A    PortID defaultPortID;
3482846SN/A
3497523SN/A    /** If true, use address range provided by default device.  Any
3507523SN/A       address not handled by another port and not in default device's
3517523SN/A       range will cause a fatal error.  If false, just send all
3527523SN/A       addresses not handled by another port to default device. */
3539240SN/A    const bool useDefaultRange;
3543489SN/A
35510405Sandreas.hansson@arm.com    BaseXBar(const BaseXBarParams *p);
3569036SN/A
35710405Sandreas.hansson@arm.com    virtual ~BaseXBar();
3589036SN/A
3599712SN/A    /**
3609712SN/A     * Stats for transaction distribution and data passing through the
36110405Sandreas.hansson@arm.com     * crossbar. The transaction distribution is globally counting
3629712SN/A     * different types of commands. The packet count and total packet
36310405Sandreas.hansson@arm.com     * size are two-dimensional vectors that are indexed by the
3649712SN/A     * slave port and master port id (thus the neighbouring master and
3659712SN/A     * neighbouring slave), summing up both directions (request and
3669712SN/A     * response).
3679712SN/A     */
3689712SN/A    Stats::Vector transDist;
3699712SN/A    Stats::Vector2d pktCount;
37010405Sandreas.hansson@arm.com    Stats::Vector2d pktSize;
3719712SN/A
3722381SN/A  public:
3732381SN/A
3749278SN/A    virtual void init();
3759278SN/A
37610405Sandreas.hansson@arm.com    /** A function used to return the port associated with this object. */
3779294SN/A    BaseMasterPort& getMasterPort(const std::string& if_name,
3789294SN/A                                  PortID idx = InvalidPortID);
3799294SN/A    BaseSlavePort& getSlavePort(const std::string& if_name,
3809294SN/A                                PortID idx = InvalidPortID);
3812568SN/A
3829342SN/A    virtual unsigned int drain(DrainManager *dm) = 0;
3833470SN/A
3849712SN/A    virtual void regStats();
3859712SN/A
3862381SN/A};
3872381SN/A
38810405Sandreas.hansson@arm.com#endif //__MEM_XBAR_HH__
389