coherent_xbar.hh revision 13808
12381SN/A/*
212341Snikos.nikoleris@arm.com * Copyright (c) 2011-2015, 2017 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 a coherent crossbar.
492381SN/A */
502381SN/A
5110405Sandreas.hansson@arm.com#ifndef __MEM_COHERENT_XBAR_HH__
5210405Sandreas.hansson@arm.com#define __MEM_COHERENT_XBAR_HH__
532381SN/A
5412351Snikos.nikoleris@arm.com#include <unordered_map>
5511859Sandreas.hansson@arm.com#include <unordered_set>
5611859Sandreas.hansson@arm.com
5710402SN/A#include "mem/snoop_filter.hh"
5810405Sandreas.hansson@arm.com#include "mem/xbar.hh"
5910405Sandreas.hansson@arm.com#include "params/CoherentXBar.hh"
602381SN/A
619036SN/A/**
6210405Sandreas.hansson@arm.com * A coherent crossbar connects a number of (potentially) snooping
6310405Sandreas.hansson@arm.com * masters and slaves, and routes the request and response packets
6410405Sandreas.hansson@arm.com * based on the address, and also forwards all requests to the
6510405Sandreas.hansson@arm.com * snoopers and deals with the snoop responses.
669036SN/A *
6710405Sandreas.hansson@arm.com * The coherent crossbar can be used as a template for modelling QPI,
6810405Sandreas.hansson@arm.com * HyperTransport, ACE and coherent OCP buses, and is typically used
6910405Sandreas.hansson@arm.com * for the L1-to-L2 buses and as the main system interconnect.  @sa
7010405Sandreas.hansson@arm.com * \ref gem5MemorySystem "gem5 Memory System"
719036SN/A */
7210405Sandreas.hansson@arm.comclass CoherentXBar : public BaseXBar
732381SN/A{
749031SN/A
759036SN/A  protected:
769036SN/A
778922SN/A    /**
7810405Sandreas.hansson@arm.com     * Declare the layers of this crossbar, one vector for requests,
7910405Sandreas.hansson@arm.com     * one for responses, and one for snoop responses
809092SN/A     */
819715SN/A    std::vector<ReqLayer*> reqLayers;
829715SN/A    std::vector<RespLayer*> respLayers;
8310713Sandreas.hansson@arm.com    std::vector<SnoopRespLayer*> snoopLayers;
849092SN/A
859092SN/A    /**
8610405Sandreas.hansson@arm.com     * Declaration of the coherent crossbar slave port type, one will
8710405Sandreas.hansson@arm.com     * be instantiated for each of the master ports connecting to the
8810405Sandreas.hansson@arm.com     * crossbar.
898922SN/A     */
9010888Sandreas.hansson@arm.com    class CoherentXBarSlavePort : public QueuedSlavePort
912381SN/A    {
929036SN/A
938922SN/A      private:
949036SN/A
9510405Sandreas.hansson@arm.com        /** A reference to the crossbar to which this port belongs. */
9610405Sandreas.hansson@arm.com        CoherentXBar &xbar;
972381SN/A
9810888Sandreas.hansson@arm.com        /** A normal packet queue used to store responses. */
9910888Sandreas.hansson@arm.com        RespPacketQueue queue;
10010888Sandreas.hansson@arm.com
1012381SN/A      public:
1022381SN/A
10310405Sandreas.hansson@arm.com        CoherentXBarSlavePort(const std::string &_name,
10410405Sandreas.hansson@arm.com                             CoherentXBar &_xbar, PortID _id)
10510888Sandreas.hansson@arm.com            : QueuedSlavePort(_name, &_xbar, queue, _id), xbar(_xbar),
10610888Sandreas.hansson@arm.com              queue(_xbar, *this)
1078922SN/A        { }
1088922SN/A
1098922SN/A      protected:
1108922SN/A
11113808Sgabeblack@google.com        bool
11213808Sgabeblack@google.com        recvTimingReq(PacketPtr pkt) override
11313808Sgabeblack@google.com        {
11413808Sgabeblack@google.com            return xbar.recvTimingReq(pkt, id);
11513808Sgabeblack@google.com        }
1168922SN/A
11713808Sgabeblack@google.com        bool
11813808Sgabeblack@google.com        recvTimingSnoopResp(PacketPtr pkt) override
11913808Sgabeblack@google.com        {
12013808Sgabeblack@google.com            return xbar.recvTimingSnoopResp(pkt, id);
12113808Sgabeblack@google.com        }
1228948SN/A
12313808Sgabeblack@google.com        Tick
12413808Sgabeblack@google.com        recvAtomic(PacketPtr pkt) override
12513808Sgabeblack@google.com        {
12613808Sgabeblack@google.com            return xbar.recvAtomic(pkt, id);
12713808Sgabeblack@google.com        }
1288922SN/A
12913808Sgabeblack@google.com        void
13013808Sgabeblack@google.com        recvFunctional(PacketPtr pkt) override
13113808Sgabeblack@google.com        {
13213808Sgabeblack@google.com            xbar.recvFunctional(pkt, id);
13313808Sgabeblack@google.com        }
1348922SN/A
13513808Sgabeblack@google.com        AddrRangeList
13613808Sgabeblack@google.com        getAddrRanges() const override
13713808Sgabeblack@google.com        {
13813808Sgabeblack@google.com            return xbar.getAddrRanges();
13913808Sgabeblack@google.com        }
1409036SN/A
1419036SN/A    };
1429036SN/A
1439036SN/A    /**
14410405Sandreas.hansson@arm.com     * Declaration of the coherent crossbar master port type, one will be
1459036SN/A     * instantiated for each of the slave interfaces connecting to the
14610405Sandreas.hansson@arm.com     * crossbar.
1479036SN/A     */
14810405Sandreas.hansson@arm.com    class CoherentXBarMasterPort : public MasterPort
1499036SN/A    {
1509036SN/A      private:
15110405Sandreas.hansson@arm.com        /** A reference to the crossbar to which this port belongs. */
15210405Sandreas.hansson@arm.com        CoherentXBar &xbar;
1539036SN/A
1549036SN/A      public:
1559036SN/A
15610405Sandreas.hansson@arm.com        CoherentXBarMasterPort(const std::string &_name,
15710405Sandreas.hansson@arm.com                              CoherentXBar &_xbar, PortID _id)
15810405Sandreas.hansson@arm.com            : MasterPort(_name, &_xbar, _id), xbar(_xbar)
1599036SN/A        { }
1609036SN/A
1619036SN/A      protected:
1629036SN/A
1639036SN/A        /**
1649036SN/A         * Determine if this port should be considered a snooper. For
16510405Sandreas.hansson@arm.com         * a coherent crossbar master port this is always true.
1669036SN/A         *
1679036SN/A         * @return a boolean that is true if this port is snooping
1689036SN/A         */
16913808Sgabeblack@google.com        bool isSnooping() const override { return true; }
1709036SN/A
17113808Sgabeblack@google.com        bool
17213808Sgabeblack@google.com        recvTimingResp(PacketPtr pkt) override
17313808Sgabeblack@google.com        {
17413808Sgabeblack@google.com            return xbar.recvTimingResp(pkt, id);
17513808Sgabeblack@google.com        }
1769036SN/A
17713808Sgabeblack@google.com        void
17813808Sgabeblack@google.com        recvTimingSnoopReq(PacketPtr pkt) override
17913808Sgabeblack@google.com        {
18013808Sgabeblack@google.com            return xbar.recvTimingSnoopReq(pkt, id);
18113808Sgabeblack@google.com        }
1829036SN/A
18313808Sgabeblack@google.com        Tick
18413808Sgabeblack@google.com        recvAtomicSnoop(PacketPtr pkt) override
18513808Sgabeblack@google.com        {
18613808Sgabeblack@google.com            return xbar.recvAtomicSnoop(pkt, id);
18713808Sgabeblack@google.com        }
1889036SN/A
18913808Sgabeblack@google.com        void
19013808Sgabeblack@google.com        recvFunctionalSnoop(PacketPtr pkt) override
19113808Sgabeblack@google.com        {
19213808Sgabeblack@google.com            xbar.recvFunctionalSnoop(pkt, id);
19313808Sgabeblack@google.com        }
1949036SN/A
19513808Sgabeblack@google.com        void recvRangeChange() override { xbar.recvRangeChange(id); }
19613808Sgabeblack@google.com        void recvReqRetry() override { xbar.recvReqRetry(id); }
1978922SN/A
1988922SN/A    };
1998922SN/A
2009716SN/A    /**
2019716SN/A     * Internal class to bridge between an incoming snoop response
2029716SN/A     * from a slave port and forwarding it through an outgoing slave
2039716SN/A     * port. It is effectively a dangling master port.
2049716SN/A     */
2059716SN/A    class SnoopRespPort : public MasterPort
2069716SN/A    {
2079716SN/A
2089716SN/A      private:
2099716SN/A
2109716SN/A        /** The port which we mirror internally. */
21110888Sandreas.hansson@arm.com        QueuedSlavePort& slavePort;
2129716SN/A
2139716SN/A      public:
2149716SN/A
2159716SN/A        /**
2169716SN/A         * Create a snoop response port that mirrors a given slave port.
2179716SN/A         */
21810888Sandreas.hansson@arm.com        SnoopRespPort(QueuedSlavePort& slave_port, CoherentXBar& _xbar) :
21910405Sandreas.hansson@arm.com            MasterPort(slave_port.name() + ".snoopRespPort", &_xbar),
2209778SN/A            slavePort(slave_port) { }
2219716SN/A
2229716SN/A        /**
2239716SN/A         * Override the sending of retries and pass them on through
2249716SN/A         * the mirrored slave port.
2259716SN/A         */
22613808Sgabeblack@google.com        void
22713808Sgabeblack@google.com        sendRetryResp() override
22813808Sgabeblack@google.com        {
22910713Sandreas.hansson@arm.com            // forward it as a snoop response retry
23010713Sandreas.hansson@arm.com            slavePort.sendRetrySnoopResp();
2319716SN/A        }
2329716SN/A
23313808Sgabeblack@google.com        void
23413808Sgabeblack@google.com        recvReqRetry() override
23513808Sgabeblack@google.com        {
23613808Sgabeblack@google.com            panic("SnoopRespPort should never see retry");
23713808Sgabeblack@google.com        }
2389716SN/A
23913808Sgabeblack@google.com        bool
24013808Sgabeblack@google.com        recvTimingResp(PacketPtr pkt) override
2419716SN/A        {
24213808Sgabeblack@google.com            panic("SnoopRespPort should never see timing response");
2439716SN/A        }
2449716SN/A
2459716SN/A    };
2469716SN/A
2479716SN/A    std::vector<SnoopRespPort*> snoopRespPorts;
2489716SN/A
24910888Sandreas.hansson@arm.com    std::vector<QueuedSlavePort*> snoopPorts;
2504475SN/A
2518948SN/A    /**
25210656Sandreas.hansson@arm.com     * Store the outstanding requests that we are expecting snoop
25310656Sandreas.hansson@arm.com     * responses from so we can determine which snoop responses we
25410656Sandreas.hansson@arm.com     * generated and which ones were merely forwarded.
2558948SN/A     */
25611168Sandreas.hansson@arm.com    std::unordered_set<RequestPtr> outstandingSnoop;
2578948SN/A
2589524SN/A    /**
25912351Snikos.nikoleris@arm.com     * Store the outstanding cache maintenance that we are expecting
26012351Snikos.nikoleris@arm.com     * snoop responses from so we can determine when we received all
26112351Snikos.nikoleris@arm.com     * snoop responses and if any of the agents satisfied the request.
26212351Snikos.nikoleris@arm.com     */
26312351Snikos.nikoleris@arm.com    std::unordered_map<PacketId, PacketPtr> outstandingCMO;
26412351Snikos.nikoleris@arm.com
26512351Snikos.nikoleris@arm.com    /**
2669524SN/A     * Keep a pointer to the system to be allow to querying memory system
2679524SN/A     * properties.
2689524SN/A     */
2699524SN/A    System *system;
2709524SN/A
27110402SN/A    /** A snoop filter that tracks cache line residency and can restrict the
27210402SN/A      * broadcast needed for probes.  NULL denotes an absent filter. */
27310402SN/A    SnoopFilter *snoopFilter;
27410402SN/A
27510719SMarco.Balboni@ARM.com    const Cycles snoopResponseLatency;
27611334Sandreas.hansson@arm.com    const bool pointOfCoherency;
27712341Snikos.nikoleris@arm.com    const bool pointOfUnification;
27812341Snikos.nikoleris@arm.com
27910883Sali.jafri@arm.com    /**
28011190Sandreas.hansson@arm.com     * Upstream caches need this packet until true is returned, so
28111190Sandreas.hansson@arm.com     * hold it for deletion until a subsequent call
28210883Sali.jafri@arm.com     */
28311190Sandreas.hansson@arm.com    std::unique_ptr<Packet> pendingDelete;
28410883Sali.jafri@arm.com
2859945SN/A    bool recvTimingReq(PacketPtr pkt, PortID slave_port_id);
2869945SN/A    bool recvTimingResp(PacketPtr pkt, PortID master_port_id);
2879945SN/A    void recvTimingSnoopReq(PacketPtr pkt, PortID master_port_id);
2889945SN/A    bool recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id);
28910713Sandreas.hansson@arm.com    void recvReqRetry(PortID master_port_id);
2909092SN/A
2918948SN/A    /**
2928948SN/A     * Forward a timing packet to our snoopers, potentially excluding
2938948SN/A     * one of the connected coherent masters to avoid sending a packet
2948948SN/A     * back to where it came from.
2958948SN/A     *
2968948SN/A     * @param pkt Packet to forward
2978948SN/A     * @param exclude_slave_port_id Id of slave port to exclude
2988948SN/A     */
29913808Sgabeblack@google.com    void
30013808Sgabeblack@google.com    forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id)
30113808Sgabeblack@google.com    {
30210402SN/A        forwardTiming(pkt, exclude_slave_port_id, snoopPorts);
30310402SN/A    }
30410402SN/A
30510402SN/A    /**
30610402SN/A     * Forward a timing packet to a selected list of snoopers, potentially
30710402SN/A     * excluding one of the connected coherent masters to avoid sending a packet
30810402SN/A     * back to where it came from.
30910402SN/A     *
31010402SN/A     * @param pkt Packet to forward
31110402SN/A     * @param exclude_slave_port_id Id of slave port to exclude
31210402SN/A     * @param dests Vector of destination ports for the forwarded pkt
31310402SN/A     */
31410402SN/A    void forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id,
31510888Sandreas.hansson@arm.com                       const std::vector<QueuedSlavePort*>& dests);
3168948SN/A
3179032SN/A    Tick recvAtomic(PacketPtr pkt, PortID slave_port_id);
3189032SN/A    Tick recvAtomicSnoop(PacketPtr pkt, PortID master_port_id);
3198948SN/A
3208948SN/A    /**
3218948SN/A     * Forward an atomic packet to our snoopers, potentially excluding
3228948SN/A     * one of the connected coherent masters to avoid sending a packet
3238948SN/A     * back to where it came from.
3248948SN/A     *
3258948SN/A     * @param pkt Packet to forward
3268948SN/A     * @param exclude_slave_port_id Id of slave port to exclude
3278948SN/A     *
3288948SN/A     * @return a pair containing the snoop response and snoop latency
3298948SN/A     */
33013808Sgabeblack@google.com    std::pair<MemCmd, Tick>
33113808Sgabeblack@google.com    forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id)
33210402SN/A    {
33310888Sandreas.hansson@arm.com        return forwardAtomic(pkt, exclude_slave_port_id, InvalidPortID,
33410888Sandreas.hansson@arm.com                             snoopPorts);
33510402SN/A    }
33610402SN/A
33710402SN/A    /**
33810402SN/A     * Forward an atomic packet to a selected list of snoopers, potentially
33910402SN/A     * excluding one of the connected coherent masters to avoid sending a packet
34010402SN/A     * back to where it came from.
34110402SN/A     *
34210402SN/A     * @param pkt Packet to forward
34310402SN/A     * @param exclude_slave_port_id Id of slave port to exclude
34410402SN/A     * @param source_master_port_id Id of the master port for snoops from below
34510402SN/A     * @param dests Vector of destination ports for the forwarded pkt
34610402SN/A     *
34710402SN/A     * @return a pair containing the snoop response and snoop latency
34810402SN/A     */
34910402SN/A    std::pair<MemCmd, Tick> forwardAtomic(PacketPtr pkt,
35010402SN/A                                          PortID exclude_slave_port_id,
35110402SN/A                                          PortID source_master_port_id,
35210888Sandreas.hansson@arm.com                                          const std::vector<QueuedSlavePort*>&
35310888Sandreas.hansson@arm.com                                          dests);
3548948SN/A
35510405Sandreas.hansson@arm.com    /** Function called by the port when the crossbar is recieving a Functional
3564475SN/A        transaction.*/
3579032SN/A    void recvFunctional(PacketPtr pkt, PortID slave_port_id);
3584475SN/A
35910405Sandreas.hansson@arm.com    /** Function called by the port when the crossbar is recieving a functional
3608948SN/A        snoop transaction.*/
3619032SN/A    void recvFunctionalSnoop(PacketPtr pkt, PortID master_port_id);
3628948SN/A
3638948SN/A    /**
3648948SN/A     * Forward a functional packet to our snoopers, potentially
3658948SN/A     * excluding one of the connected coherent masters to avoid
3668948SN/A     * sending a packet back to where it came from.
3678948SN/A     *
3688948SN/A     * @param pkt Packet to forward
3698948SN/A     * @param exclude_slave_port_id Id of slave port to exclude
3708948SN/A     */
3719031SN/A    void forwardFunctional(PacketPtr pkt, PortID exclude_slave_port_id);
3728948SN/A
37311334Sandreas.hansson@arm.com    /**
37411334Sandreas.hansson@arm.com     * Determine if the crossbar should sink the packet, as opposed to
37511334Sandreas.hansson@arm.com     * forwarding it, or responding.
37611334Sandreas.hansson@arm.com     */
37711334Sandreas.hansson@arm.com    bool sinkPacket(const PacketPtr pkt) const;
37811334Sandreas.hansson@arm.com
37912346Snikos.nikoleris@arm.com    /**
38012346Snikos.nikoleris@arm.com     * Determine if the crossbar should forward the packet, as opposed to
38112346Snikos.nikoleris@arm.com     * responding to it.
38212346Snikos.nikoleris@arm.com     */
38312346Snikos.nikoleris@arm.com    bool forwardPacket(const PacketPtr pkt);
38412346Snikos.nikoleris@arm.com
38512346Snikos.nikoleris@arm.com    /**
38612346Snikos.nikoleris@arm.com     * Determine if the packet's destination is the memory below
38712346Snikos.nikoleris@arm.com     *
38812346Snikos.nikoleris@arm.com     * The memory below is the destination for a cache mainteance
38912346Snikos.nikoleris@arm.com     * operation to the Point of Coherence/Unification if this is the
39012346Snikos.nikoleris@arm.com     * Point of Coherence/Unification.
39112346Snikos.nikoleris@arm.com     *
39212346Snikos.nikoleris@arm.com     * @param pkt The processed packet
39312346Snikos.nikoleris@arm.com     *
39412346Snikos.nikoleris@arm.com     * @return Whether the memory below is the destination for the packet
39512346Snikos.nikoleris@arm.com     */
39613808Sgabeblack@google.com    bool
39713808Sgabeblack@google.com    isDestination(const PacketPtr pkt) const
39812346Snikos.nikoleris@arm.com    {
39912346Snikos.nikoleris@arm.com        return (pkt->req->isToPOC() && pointOfCoherency) ||
40012346Snikos.nikoleris@arm.com            (pkt->req->isToPOU() && pointOfUnification);
40112346Snikos.nikoleris@arm.com    }
40212346Snikos.nikoleris@arm.com
40310405Sandreas.hansson@arm.com    Stats::Scalar snoops;
40411564Sdavid.guillen@arm.com    Stats::Scalar snoopTraffic;
40510401SN/A    Stats::Distribution snoopFanout;
4069712SN/A
4072381SN/A  public:
4082381SN/A
4099036SN/A    virtual void init();
4102568SN/A
41110405Sandreas.hansson@arm.com    CoherentXBar(const CoherentXBarParams *p);
4129092SN/A
41310405Sandreas.hansson@arm.com    virtual ~CoherentXBar();
4149715SN/A
4159712SN/A    virtual void regStats();
4162381SN/A};
4172381SN/A
41810405Sandreas.hansson@arm.com#endif //__MEM_COHERENT_XBAR_HH__
419