xbar.hh revision 13799
12381SN/A/*
212780Snikos.nikoleris@arm.com * Copyright (c) 2011-2015, 2018 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>
5511168Sandreas.hansson@arm.com#include <unordered_map>
562381SN/A
579235SN/A#include "base/addr_range_map.hh"
586215SN/A#include "base/types.hh"
592381SN/A#include "mem/mem_object.hh"
6010888Sandreas.hansson@arm.com#include "mem/qport.hh"
6110405Sandreas.hansson@arm.com#include "params/BaseXBar.hh"
629712SN/A#include "sim/stats.hh"
632381SN/A
649036SN/A/**
6510405Sandreas.hansson@arm.com * The base crossbar contains the common elements of the non-coherent
6610405Sandreas.hansson@arm.com * and coherent crossbar. It is an abstract class that does not have
6710405Sandreas.hansson@arm.com * any of the functionality relating to the actual reception and
6810405Sandreas.hansson@arm.com * transmission of packets, as this is left for the subclasses.
699036SN/A *
7010405Sandreas.hansson@arm.com * The BaseXBar is responsible for the basic flow control (busy or
719036SN/A * not), the administration of retries, and the address decoding.
729036SN/A */
7310405Sandreas.hansson@arm.comclass BaseXBar : public MemObject
742381SN/A{
759031SN/A
769036SN/A  protected:
772381SN/A
789091SN/A    /**
7910405Sandreas.hansson@arm.com     * A layer is an internal crossbar arbitration point with its own
8010405Sandreas.hansson@arm.com     * flow control. Each layer is a converging multiplexer tree. By
8110405Sandreas.hansson@arm.com     * instantiating one layer per destination port (and per packet
8210405Sandreas.hansson@arm.com     * type, i.e. request, response, snoop request and snoop
8310405Sandreas.hansson@arm.com     * response), we model full crossbar structures like AXI, ACE,
8410405Sandreas.hansson@arm.com     * PCIe, etc.
859093SN/A     *
869093SN/A     * The template parameter, PortClass, indicates the destination
8710405Sandreas.hansson@arm.com     * port type for the layer. The retry list holds either master
8810405Sandreas.hansson@arm.com     * ports or slave ports, depending on the direction of the
8910405Sandreas.hansson@arm.com     * layer. Thus, a request layer has a retry list containing slave
9010405Sandreas.hansson@arm.com     * ports, whereas a response layer holds master ports.
919091SN/A     */
929715SN/A    template <typename SrcType, typename DstType>
939342SN/A    class Layer : public Drainable
949092SN/A    {
959091SN/A
969092SN/A      public:
979092SN/A
989092SN/A        /**
9910405Sandreas.hansson@arm.com         * Create a layer and give it a name. The layer uses
10010405Sandreas.hansson@arm.com         * the crossbar an event manager.
1019092SN/A         *
1029715SN/A         * @param _port destination port the layer converges at
10310405Sandreas.hansson@arm.com         * @param _xbar the crossbar this layer belongs to
1049092SN/A         * @param _name the layer's name
1059092SN/A         */
10610405Sandreas.hansson@arm.com        Layer(DstType& _port, BaseXBar& _xbar, const std::string& _name);
1079092SN/A
1089092SN/A        /**
10910405Sandreas.hansson@arm.com         * Drain according to the normal semantics, so that the crossbar
1109092SN/A         * can tell the layer to drain, and pass an event to signal
1119092SN/A         * back when drained.
1129092SN/A         *
1139092SN/A         * @param de drain event to call once drained
1149092SN/A         *
1159092SN/A         * @return 1 if busy or waiting to retry, or 0 if idle
1169092SN/A         */
11711168Sandreas.hansson@arm.com        DrainState drain() override;
1189092SN/A
1199092SN/A        /**
12010405Sandreas.hansson@arm.com         * Get the crossbar layer's name
1219092SN/A         */
12210405Sandreas.hansson@arm.com        const std::string name() const { return xbar.name() + _name; }
1239092SN/A
1249092SN/A
1259092SN/A        /**
12610405Sandreas.hansson@arm.com         * Determine if the layer accepts a packet from a specific
1279092SN/A         * port. If not, the port in question is also added to the
1289612SN/A         * retry list. In either case the state of the layer is
1299714SN/A         * updated accordingly.
1309092SN/A         *
1319612SN/A         * @param port Source port presenting the packet
1329092SN/A         *
13310405Sandreas.hansson@arm.com         * @return True if the layer accepts the packet
1349092SN/A         */
1359715SN/A        bool tryTiming(SrcType* src_port);
1369092SN/A
1379092SN/A        /**
1389092SN/A         * Deal with a destination port accepting a packet by potentially
1399092SN/A         * removing the source port from the retry list (if retrying) and
14010405Sandreas.hansson@arm.com         * occupying the layer accordingly.
1419092SN/A         *
1429092SN/A         * @param busy_time Time to spend as a result of a successful send
1439092SN/A         */
1449092SN/A        void succeededTiming(Tick busy_time);
1459092SN/A
1469092SN/A        /**
1479092SN/A         * Deal with a destination port not accepting a packet by
1489092SN/A         * potentially adding the source port to the retry list (if
14910405Sandreas.hansson@arm.com         * not already at the front) and occupying the layer
1509092SN/A         * accordingly.
1519092SN/A         *
1529612SN/A         * @param src_port Source port
1539092SN/A         * @param busy_time Time to spend as a result of a failed send
1549092SN/A         */
1559715SN/A        void failedTiming(SrcType* src_port, Tick busy_time);
1569092SN/A
15710405Sandreas.hansson@arm.com        /** Occupy the layer until until */
1589092SN/A        void occupyLayer(Tick until);
1599092SN/A
1609092SN/A        /**
1619612SN/A         * Send a retry to the port at the head of waitingForLayer. The
1629092SN/A         * caller must ensure that the list is not empty.
1639092SN/A         */
1649092SN/A        void retryWaiting();
1659092SN/A
1669092SN/A        /**
1679612SN/A         * Handle a retry from a neighbouring module. This wraps
1689092SN/A         * retryWaiting by verifying that there are ports waiting
1699092SN/A         * before calling retryWaiting.
1709092SN/A         */
1719715SN/A        void recvRetry();
1729092SN/A
1739712SN/A        /**
1749712SN/A         * Register stats for the layer
1759712SN/A         */
1769712SN/A        void regStats();
1779712SN/A
17810713Sandreas.hansson@arm.com      protected:
17910713Sandreas.hansson@arm.com
18010713Sandreas.hansson@arm.com        /**
18110713Sandreas.hansson@arm.com         * Sending the actual retry, in a manner specific to the
18210713Sandreas.hansson@arm.com         * individual layers. Note that for a MasterPort, there is
18310713Sandreas.hansson@arm.com         * both a RequestLayer and a SnoopResponseLayer using the same
18410713Sandreas.hansson@arm.com         * port, but using different functions for the flow control.
18510713Sandreas.hansson@arm.com         */
18610713Sandreas.hansson@arm.com        virtual void sendRetry(SrcType* retry_port) = 0;
18710713Sandreas.hansson@arm.com
1889092SN/A      private:
1899092SN/A
1909715SN/A        /** The destination port this layer converges at. */
1919715SN/A        DstType& port;
1929715SN/A
19310405Sandreas.hansson@arm.com        /** The crossbar this layer is a part of. */
19410405Sandreas.hansson@arm.com        BaseXBar& xbar;
1959092SN/A
1969092SN/A        /** A name for this layer. */
1979092SN/A        std::string _name;
1989092SN/A
1999092SN/A        /**
20010405Sandreas.hansson@arm.com         * We declare an enum to track the state of the layer. The
20110405Sandreas.hansson@arm.com         * starting point is an idle state where the layer is waiting
20210405Sandreas.hansson@arm.com         * for a packet to arrive. Upon arrival, the layer
2039092SN/A         * transitions to the busy state, where it remains either
2049092SN/A         * until the packet transfer is done, or the header time is
20510405Sandreas.hansson@arm.com         * spent. Once the layer leaves the busy state, it can
2069092SN/A         * either go back to idle, if no packets have arrived while it
20710405Sandreas.hansson@arm.com         * was busy, or the layer goes on to retry the first port
2089612SN/A         * in waitingForLayer. A similar transition takes place from
20910405Sandreas.hansson@arm.com         * idle to retry if the layer receives a retry from one of
2109092SN/A         * its connected ports. The retry state lasts until the port
2119092SN/A         * in questions calls sendTiming and returns control to the
21210405Sandreas.hansson@arm.com         * layer, or goes to a busy state if the port does not
2139092SN/A         * immediately react to the retry by calling sendTiming.
2149092SN/A         */
2159092SN/A        enum State { IDLE, BUSY, RETRY };
2169092SN/A
21710405Sandreas.hansson@arm.com        /** track the state of the layer */
2189092SN/A        State state;
2199092SN/A
2209092SN/A        /**
2219612SN/A         * A deque of ports that retry should be called on because
2229612SN/A         * the original send was delayed due to a busy layer.
2239092SN/A         */
2249715SN/A        std::deque<SrcType*> waitingForLayer;
2259092SN/A
2269092SN/A        /**
2279715SN/A         * Track who is waiting for the retry when receiving it from a
2289715SN/A         * peer. If no port is waiting NULL is stored.
2299612SN/A         */
2309715SN/A        SrcType* waitingForPeer;
2319612SN/A
2329612SN/A        /**
23310405Sandreas.hansson@arm.com         * Release the layer after being occupied and return to an
2349092SN/A         * idle state where we proceed to send a retry to any
2359092SN/A         * potential waiting port, or drain if asked to do so.
2369092SN/A         */
2379092SN/A        void releaseLayer();
2389092SN/A
2399092SN/A        /** event used to schedule a release of the layer */
24012084Sspwilson2@wisc.edu        EventFunctionWrapper releaseEvent;
2419092SN/A
2429712SN/A        /**
2439712SN/A         * Stats for occupancy and utilization. These stats capture
24410405Sandreas.hansson@arm.com         * the time the layer spends in the busy state and are thus only
2459712SN/A         * relevant when the memory system is in timing mode.
2469712SN/A         */
2479712SN/A        Stats::Scalar occupancy;
2489712SN/A        Stats::Formula utilization;
2499712SN/A
2509092SN/A    };
2519091SN/A
25210713Sandreas.hansson@arm.com    class ReqLayer : public Layer<SlavePort,MasterPort>
25310713Sandreas.hansson@arm.com    {
25410713Sandreas.hansson@arm.com      public:
25510713Sandreas.hansson@arm.com        /**
25610713Sandreas.hansson@arm.com         * Create a request layer and give it a name.
25710713Sandreas.hansson@arm.com         *
25810713Sandreas.hansson@arm.com         * @param _port destination port the layer converges at
25910713Sandreas.hansson@arm.com         * @param _xbar the crossbar this layer belongs to
26010713Sandreas.hansson@arm.com         * @param _name the layer's name
26110713Sandreas.hansson@arm.com         */
26210713Sandreas.hansson@arm.com        ReqLayer(MasterPort& _port, BaseXBar& _xbar, const std::string& _name) :
26310713Sandreas.hansson@arm.com            Layer(_port, _xbar, _name) {}
26410713Sandreas.hansson@arm.com
26510713Sandreas.hansson@arm.com      protected:
26610713Sandreas.hansson@arm.com
26710713Sandreas.hansson@arm.com        void sendRetry(SlavePort* retry_port)
26810713Sandreas.hansson@arm.com        { retry_port->sendRetryReq(); }
26910713Sandreas.hansson@arm.com    };
27010713Sandreas.hansson@arm.com
27110713Sandreas.hansson@arm.com    class RespLayer : public Layer<MasterPort,SlavePort>
27210713Sandreas.hansson@arm.com    {
27310713Sandreas.hansson@arm.com      public:
27410713Sandreas.hansson@arm.com        /**
27510713Sandreas.hansson@arm.com         * Create a response layer and give it a name.
27610713Sandreas.hansson@arm.com         *
27710713Sandreas.hansson@arm.com         * @param _port destination port the layer converges at
27810713Sandreas.hansson@arm.com         * @param _xbar the crossbar this layer belongs to
27910713Sandreas.hansson@arm.com         * @param _name the layer's name
28010713Sandreas.hansson@arm.com         */
28110713Sandreas.hansson@arm.com        RespLayer(SlavePort& _port, BaseXBar& _xbar, const std::string& _name) :
28210713Sandreas.hansson@arm.com            Layer(_port, _xbar, _name) {}
28310713Sandreas.hansson@arm.com
28410713Sandreas.hansson@arm.com      protected:
28510713Sandreas.hansson@arm.com
28610713Sandreas.hansson@arm.com        void sendRetry(MasterPort* retry_port)
28710713Sandreas.hansson@arm.com        { retry_port->sendRetryResp(); }
28810713Sandreas.hansson@arm.com    };
28910713Sandreas.hansson@arm.com
29010713Sandreas.hansson@arm.com    class SnoopRespLayer : public Layer<SlavePort,MasterPort>
29110713Sandreas.hansson@arm.com    {
29210713Sandreas.hansson@arm.com      public:
29310713Sandreas.hansson@arm.com        /**
29410713Sandreas.hansson@arm.com         * Create a snoop response layer and give it a name.
29510713Sandreas.hansson@arm.com         *
29610713Sandreas.hansson@arm.com         * @param _port destination port the layer converges at
29710713Sandreas.hansson@arm.com         * @param _xbar the crossbar this layer belongs to
29810713Sandreas.hansson@arm.com         * @param _name the layer's name
29910713Sandreas.hansson@arm.com         */
30010713Sandreas.hansson@arm.com        SnoopRespLayer(MasterPort& _port, BaseXBar& _xbar,
30110713Sandreas.hansson@arm.com                       const std::string& _name) :
30210713Sandreas.hansson@arm.com            Layer(_port, _xbar, _name) {}
30310713Sandreas.hansson@arm.com
30410713Sandreas.hansson@arm.com      protected:
30510713Sandreas.hansson@arm.com
30610713Sandreas.hansson@arm.com        void sendRetry(SlavePort* retry_port)
30710713Sandreas.hansson@arm.com        { retry_port->sendRetrySnoopResp(); }
30810713Sandreas.hansson@arm.com    };
30910713Sandreas.hansson@arm.com
31010719SMarco.Balboni@ARM.com    /**
31110719SMarco.Balboni@ARM.com     * Cycles of front-end pipeline including the delay to accept the request
31210719SMarco.Balboni@ARM.com     * and to decode the address.
31310719SMarco.Balboni@ARM.com     */
31410719SMarco.Balboni@ARM.com    const Cycles frontendLatency;
31510719SMarco.Balboni@ARM.com    /** Cycles of forward latency */
31610719SMarco.Balboni@ARM.com    const Cycles forwardLatency;
31710719SMarco.Balboni@ARM.com    /** Cycles of response latency */
31810719SMarco.Balboni@ARM.com    const Cycles responseLatency;
31910405Sandreas.hansson@arm.com    /** the width of the xbar in bytes */
3209240SN/A    const uint32_t width;
3214475SN/A
32212778Sgabeblack@google.com    AddrRangeMap<PortID, 3> portMap;
3234475SN/A
32410656Sandreas.hansson@arm.com    /**
32510656Sandreas.hansson@arm.com     * Remember where request packets came from so that we can route
32610656Sandreas.hansson@arm.com     * responses to the appropriate port. This relies on the fact that
32710656Sandreas.hansson@arm.com     * the underlying Request pointer inside the Packet stays
32810656Sandreas.hansson@arm.com     * constant.
32910656Sandreas.hansson@arm.com     */
33011168Sandreas.hansson@arm.com    std::unordered_map<RequestPtr, PortID> routeTo;
33110656Sandreas.hansson@arm.com
33210405Sandreas.hansson@arm.com    /** all contigous ranges seen by this crossbar */
33310405Sandreas.hansson@arm.com    AddrRangeList xbarRanges;
3349564SN/A
3359279SN/A    AddrRange defaultRange;
3364475SN/A
3378948SN/A    /**
33810405Sandreas.hansson@arm.com     * Function called by the port when the crossbar is recieving a
33910405Sandreas.hansson@arm.com     * range change.
3409032SN/A     *
3419032SN/A     * @param master_port_id id of the port that received the change
3429032SN/A     */
34311186Serfan.azarkhish@unibo.it    virtual void recvRangeChange(PortID master_port_id);
3444475SN/A
34512780Snikos.nikoleris@arm.com    /**
34612780Snikos.nikoleris@arm.com     * Find which port connected to this crossbar (if any) should be
34712780Snikos.nikoleris@arm.com     * given a packet with this address range.
34810405Sandreas.hansson@arm.com     *
34912780Snikos.nikoleris@arm.com     * @param addr_range Address range to find port for.
3504894SN/A     * @return id of port that the packet should be sent out of.
3514475SN/A     */
35212780Snikos.nikoleris@arm.com    PortID findPort(AddrRange addr_range);
3534475SN/A
3548711SN/A    /**
35510405Sandreas.hansson@arm.com     * Return the address ranges the crossbar is responsible for.
3568711SN/A     *
3578711SN/A     * @return a list of non-overlapping address ranges
3584475SN/A     */
3599090SN/A    AddrRangeList getAddrRanges() const;
3608711SN/A
3619547SN/A    /**
3629547SN/A     * Calculate the timing parameters for the packet. Updates the
36310694SMarco.Balboni@ARM.com     * headerDelay and payloadDelay fields of the packet
3649547SN/A     * object with the relative number of ticks required to transmit
36510694SMarco.Balboni@ARM.com     * the header and the payload, respectively.
36610719SMarco.Balboni@ARM.com     *
36710719SMarco.Balboni@ARM.com     * @param pkt Packet to populate with timings
36810719SMarco.Balboni@ARM.com     * @param header_delay Header delay to be added
3695354SN/A     */
37010719SMarco.Balboni@ARM.com    void calcPacketTiming(PacketPtr pkt, Tick header_delay);
3715354SN/A
3729032SN/A    /**
37310405Sandreas.hansson@arm.com     * Remember for each of the master ports of the crossbar if we got
37410405Sandreas.hansson@arm.com     * an address range from the connected slave. For convenience,
37510405Sandreas.hansson@arm.com     * also keep track of if we got ranges from all the slave modules
37610405Sandreas.hansson@arm.com     * or not.
3779279SN/A     */
3789279SN/A    std::vector<bool> gotAddrRanges;
3799279SN/A    bool gotAllAddrRanges;
3803159SN/A
38110405Sandreas.hansson@arm.com    /** The master and slave ports of the crossbar */
38210888Sandreas.hansson@arm.com    std::vector<QueuedSlavePort*> slavePorts;
3838966SN/A    std::vector<MasterPort*> masterPorts;
3848966SN/A
3852846SN/A    /** Port that handles requests that don't match any of the interfaces.*/
3869031SN/A    PortID defaultPortID;
3872846SN/A
3887523SN/A    /** If true, use address range provided by default device.  Any
3897523SN/A       address not handled by another port and not in default device's
3907523SN/A       range will cause a fatal error.  If false, just send all
3917523SN/A       addresses not handled by another port to default device. */
3929240SN/A    const bool useDefaultRange;
3933489SN/A
39410405Sandreas.hansson@arm.com    BaseXBar(const BaseXBarParams *p);
3959036SN/A
3969712SN/A    /**
3979712SN/A     * Stats for transaction distribution and data passing through the
39810405Sandreas.hansson@arm.com     * crossbar. The transaction distribution is globally counting
3999712SN/A     * different types of commands. The packet count and total packet
40010405Sandreas.hansson@arm.com     * size are two-dimensional vectors that are indexed by the
4019712SN/A     * slave port and master port id (thus the neighbouring master and
4029712SN/A     * neighbouring slave), summing up both directions (request and
4039712SN/A     * response).
4049712SN/A     */
4059712SN/A    Stats::Vector transDist;
4069712SN/A    Stats::Vector2d pktCount;
40710405Sandreas.hansson@arm.com    Stats::Vector2d pktSize;
4089712SN/A
4092381SN/A  public:
4102381SN/A
41111767Sandreas.sandberg@arm.com    virtual ~BaseXBar();
41211767Sandreas.sandberg@arm.com
41313799SAndrea.Mondelli@ucf.edu    void init() override;
4149278SN/A
41510405Sandreas.hansson@arm.com    /** A function used to return the port associated with this object. */
41613784Sgabeblack@google.com    Port &getPort(const std::string &if_name,
41713784Sgabeblack@google.com                  PortID idx=InvalidPortID) override;
4182568SN/A
41913799SAndrea.Mondelli@ucf.edu    void regStats() override;
4209712SN/A
4212381SN/A};
4222381SN/A
42310405Sandreas.hansson@arm.com#endif //__MEM_XBAR_HH__
424