port.hh revision 12342
19651SAndreas.Sandberg@ARM.com/*
210858Sandreas.sandberg@arm.com * Copyright (c) 2011-2012,2015,2017 ARM Limited
39651SAndreas.Sandberg@ARM.com * All rights reserved
49651SAndreas.Sandberg@ARM.com *
59651SAndreas.Sandberg@ARM.com * The license below extends only to copyright in the software and shall
69651SAndreas.Sandberg@ARM.com * not be construed as granting a license to any other intellectual
79651SAndreas.Sandberg@ARM.com * property including but not limited to intellectual property relating
89651SAndreas.Sandberg@ARM.com * to a hardware implementation of the functionality of the software
99651SAndreas.Sandberg@ARM.com * licensed hereunder.  You may use the software subject to the license
109651SAndreas.Sandberg@ARM.com * terms below provided that you ensure that this notice is replicated
119651SAndreas.Sandberg@ARM.com * unmodified and in its entirety in all distributions of the software,
129651SAndreas.Sandberg@ARM.com * modified or unmodified, in source code or in binary form.
139651SAndreas.Sandberg@ARM.com *
149651SAndreas.Sandberg@ARM.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
159651SAndreas.Sandberg@ARM.com * All rights reserved.
169651SAndreas.Sandberg@ARM.com *
179651SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without
189651SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are
199651SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright
209651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer;
219651SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright
229651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the
239651SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution;
249651SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its
259651SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from
269651SAndreas.Sandberg@ARM.com * this software without specific prior written permission.
279651SAndreas.Sandberg@ARM.com *
289651SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
299651SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
309651SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
319651SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
329651SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
339651SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
349651SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
359651SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
369651SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
379651SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
389651SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
399651SAndreas.Sandberg@ARM.com *
4011793Sbrandon.potter@amd.com * Authors: Ron Dreslinski
4111793Sbrandon.potter@amd.com *          Andreas Hansson
429651SAndreas.Sandberg@ARM.com *          William Wang
439651SAndreas.Sandberg@ARM.com */
449651SAndreas.Sandberg@ARM.com
459651SAndreas.Sandberg@ARM.com/**
469651SAndreas.Sandberg@ARM.com * @file
479651SAndreas.Sandberg@ARM.com * Port Object Declaration.
489651SAndreas.Sandberg@ARM.com */
499651SAndreas.Sandberg@ARM.com
509651SAndreas.Sandberg@ARM.com#ifndef __MEM_PORT_HH__
519760Sandreas@sandberg.pp.se#define __MEM_PORT_HH__
529651SAndreas.Sandberg@ARM.com
539683Sandreas@sandberg.pp.se#include "base/addr_range.hh"
549753Sandreas@sandberg.pp.se#include "mem/packet.hh"
559651SAndreas.Sandberg@ARM.com
569651SAndreas.Sandberg@ARM.comclass MemObject;
579651SAndreas.Sandberg@ARM.com
589651SAndreas.Sandberg@ARM.com/**
599651SAndreas.Sandberg@ARM.com * Ports are used to interface memory objects to each other. A port is
609651SAndreas.Sandberg@ARM.com * either a master or a slave and the connected peer is always of the
619651SAndreas.Sandberg@ARM.com * opposite role. Each port has a name, an owner, and an identifier.
629651SAndreas.Sandberg@ARM.com */
639651SAndreas.Sandberg@ARM.comclass Port
649651SAndreas.Sandberg@ARM.com{
659651SAndreas.Sandberg@ARM.com
669651SAndreas.Sandberg@ARM.com  private:
6711839SCurtis.Dunham@arm.com
689651SAndreas.Sandberg@ARM.com    /** Descriptive name (for DPRINTF output) */
699651SAndreas.Sandberg@ARM.com    std::string portName;
709651SAndreas.Sandberg@ARM.com
7111399Sandreas.sandberg@arm.com  protected:
729652SAndreas.Sandberg@ARM.com
739652SAndreas.Sandberg@ARM.com    /**
749651SAndreas.Sandberg@ARM.com     * A numeric identifier to distinguish ports in a vector, and set
759651SAndreas.Sandberg@ARM.com     * to InvalidPortID in case this port is not part of a vector.
769651SAndreas.Sandberg@ARM.com     */
779651SAndreas.Sandberg@ARM.com    const PortID id;
789892Sandreas@sandberg.pp.se
799655SAndreas.Sandberg@ARM.com    /** A reference to the MemObject that owns this port. */
809752Sandreas@sandberg.pp.se    MemObject& owner;
819752Sandreas@sandberg.pp.se
829651SAndreas.Sandberg@ARM.com    /**
839651SAndreas.Sandberg@ARM.com     * Abstract base class for ports
849651SAndreas.Sandberg@ARM.com     *
859651SAndreas.Sandberg@ARM.com     * @param _name Port name including the owners name
869651SAndreas.Sandberg@ARM.com     * @param _owner The MemObject that is the structural owner of this port
8710553Salexandru.dutu@amd.com     * @param _id A port identifier for vector ports
8810553Salexandru.dutu@amd.com     */
8910553Salexandru.dutu@amd.com    Port(const std::string& _name, MemObject& _owner, PortID _id);
9010553Salexandru.dutu@amd.com
9110553Salexandru.dutu@amd.com    /**
9210553Salexandru.dutu@amd.com     * Virtual destructor due to inheritance.
9310553Salexandru.dutu@amd.com     */
9410553Salexandru.dutu@amd.com    virtual ~Port();
959651SAndreas.Sandberg@ARM.com
969651SAndreas.Sandberg@ARM.com  public:
979651SAndreas.Sandberg@ARM.com
989651SAndreas.Sandberg@ARM.com    /** Return port name (for DPRINTF). */
999651SAndreas.Sandberg@ARM.com    const std::string name() const { return portName; }
1009651SAndreas.Sandberg@ARM.com
1019651SAndreas.Sandberg@ARM.com    /** Get the port id. */
1029651SAndreas.Sandberg@ARM.com    PortID getId() const { return id; }
1039651SAndreas.Sandberg@ARM.com
1049651SAndreas.Sandberg@ARM.com};
1059651SAndreas.Sandberg@ARM.com
1069651SAndreas.Sandberg@ARM.com/** Forward declaration */
1079651SAndreas.Sandberg@ARM.comclass BaseSlavePort;
1089651SAndreas.Sandberg@ARM.com
1099651SAndreas.Sandberg@ARM.com/**
1109651SAndreas.Sandberg@ARM.com * A BaseMasterPort is a protocol-agnostic master port, responsible
1119651SAndreas.Sandberg@ARM.com * only for the structural connection to a slave port. The final
1129651SAndreas.Sandberg@ARM.com * master port that inherits from the base class must override the
1139651SAndreas.Sandberg@ARM.com * bind member function for the specific slave port class.
1149651SAndreas.Sandberg@ARM.com */
1159651SAndreas.Sandberg@ARM.comclass BaseMasterPort : public Port
1169651SAndreas.Sandberg@ARM.com{
1179651SAndreas.Sandberg@ARM.com
1189651SAndreas.Sandberg@ARM.com  protected:
1199651SAndreas.Sandberg@ARM.com
1209651SAndreas.Sandberg@ARM.com    BaseSlavePort* _baseSlavePort;
1219651SAndreas.Sandberg@ARM.com
1229651SAndreas.Sandberg@ARM.com    BaseMasterPort(const std::string& name, MemObject* owner,
1239651SAndreas.Sandberg@ARM.com                   PortID id = InvalidPortID);
1249651SAndreas.Sandberg@ARM.com    virtual ~BaseMasterPort();
1259690Sandreas@sandberg.pp.se
1269690Sandreas@sandberg.pp.se  public:
1279690Sandreas@sandberg.pp.se
12811363Sandreas@sandberg.pp.se    virtual void bind(BaseSlavePort& slave_port) = 0;
1299651SAndreas.Sandberg@ARM.com    virtual void unbind() = 0;
1309651SAndreas.Sandberg@ARM.com    BaseSlavePort& getSlavePort() const;
1319651SAndreas.Sandberg@ARM.com    bool isConnected() const;
1329651SAndreas.Sandberg@ARM.com
1339651SAndreas.Sandberg@ARM.com};
1349651SAndreas.Sandberg@ARM.com
1359651SAndreas.Sandberg@ARM.com/**
1369651SAndreas.Sandberg@ARM.com * A BaseSlavePort is a protocol-agnostic slave port, responsible
1379651SAndreas.Sandberg@ARM.com * only for the structural connection to a master port.
1389651SAndreas.Sandberg@ARM.com */
1399651SAndreas.Sandberg@ARM.comclass BaseSlavePort : public Port
1409651SAndreas.Sandberg@ARM.com{
1419651SAndreas.Sandberg@ARM.com
1429651SAndreas.Sandberg@ARM.com  protected:
1439651SAndreas.Sandberg@ARM.com
1449651SAndreas.Sandberg@ARM.com    BaseMasterPort* _baseMasterPort;
1459651SAndreas.Sandberg@ARM.com
1469651SAndreas.Sandberg@ARM.com    BaseSlavePort(const std::string& name, MemObject* owner,
1479651SAndreas.Sandberg@ARM.com                  PortID id = InvalidPortID);
1489651SAndreas.Sandberg@ARM.com    virtual ~BaseSlavePort();
1499651SAndreas.Sandberg@ARM.com
1509651SAndreas.Sandberg@ARM.com  public:
1519651SAndreas.Sandberg@ARM.com
1529651SAndreas.Sandberg@ARM.com    BaseMasterPort& getMasterPort() const;
1539651SAndreas.Sandberg@ARM.com    bool isConnected() const;
1549690Sandreas@sandberg.pp.se
1559690Sandreas@sandberg.pp.se};
1569690Sandreas@sandberg.pp.se
1579651SAndreas.Sandberg@ARM.com/** Forward declaration */
1589651SAndreas.Sandberg@ARM.comclass SlavePort;
1599651SAndreas.Sandberg@ARM.com
1609651SAndreas.Sandberg@ARM.com/**
1619651SAndreas.Sandberg@ARM.com * A MasterPort is a specialisation of a BaseMasterPort, which
1629651SAndreas.Sandberg@ARM.com * implements the default protocol for the three different level of
1639732Sandreas@sandberg.pp.se * transport functions. In addition to the basic functionality of
1649732Sandreas@sandberg.pp.se * sending packets, it also has functions to receive range changes or
16510073Sandreas@sandberg.pp.se * determine if the port is snooping or not.
16610073Sandreas@sandberg.pp.se */
16710073Sandreas@sandberg.pp.seclass MasterPort : public BaseMasterPort
16810073Sandreas@sandberg.pp.se{
16910073Sandreas@sandberg.pp.se
17010073Sandreas@sandberg.pp.se    friend class SlavePort;
17110073Sandreas@sandberg.pp.se
17211629Smichael.lebeane@amd.com  private:
17311629Smichael.lebeane@amd.com
17411629Smichael.lebeane@amd.com    SlavePort* _slavePort;
17511629Smichael.lebeane@amd.com
17611629Smichael.lebeane@amd.com  public:
17711629Smichael.lebeane@amd.com
17811629Smichael.lebeane@amd.com    MasterPort(const std::string& name, MemObject* owner,
17911629Smichael.lebeane@amd.com               PortID id = InvalidPortID);
18011629Smichael.lebeane@amd.com    virtual ~MasterPort();
18111629Smichael.lebeane@amd.com
18211629Smichael.lebeane@amd.com    /**
18311629Smichael.lebeane@amd.com     * Bind this master port to a slave port. This also does the
18411629Smichael.lebeane@amd.com     * mirror action and binds the slave port to the master port.
18511629Smichael.lebeane@amd.com     */
18611629Smichael.lebeane@amd.com    void bind(BaseSlavePort& slave_port);
18711629Smichael.lebeane@amd.com
18811629Smichael.lebeane@amd.com    /**
18911629Smichael.lebeane@amd.com     * Unbind this master port and the associated slave port.
19011629Smichael.lebeane@amd.com     */
19111629Smichael.lebeane@amd.com    void unbind();
19211629Smichael.lebeane@amd.com
19311629Smichael.lebeane@amd.com    /**
19411629Smichael.lebeane@amd.com     * Send an atomic request packet, where the data is moved and the
19511629Smichael.lebeane@amd.com     * state is updated in zero time, without interleaving with other
19611629Smichael.lebeane@amd.com     * memory accesses.
19711629Smichael.lebeane@amd.com     *
19811629Smichael.lebeane@amd.com     * @param pkt Packet to send.
19911629Smichael.lebeane@amd.com     *
20011629Smichael.lebeane@amd.com     * @return Estimated latency of access.
20111629Smichael.lebeane@amd.com     */
20211629Smichael.lebeane@amd.com    Tick sendAtomic(PacketPtr pkt);
20311629Smichael.lebeane@amd.com
20411629Smichael.lebeane@amd.com    /**
20511629Smichael.lebeane@amd.com     * Send a functional request packet, where the data is instantly
20611629Smichael.lebeane@amd.com     * updated everywhere in the memory system, without affecting the
20711629Smichael.lebeane@amd.com     * current state of any block or moving the block.
20811629Smichael.lebeane@amd.com     *
20911629Smichael.lebeane@amd.com     * @param pkt Packet to send.
21011629Smichael.lebeane@amd.com     */
21111629Smichael.lebeane@amd.com    void sendFunctional(PacketPtr pkt);
21211629Smichael.lebeane@amd.com
21311629Smichael.lebeane@amd.com    /**
21411629Smichael.lebeane@amd.com     * Attempt to send a timing request to the slave port by calling
21511629Smichael.lebeane@amd.com     * its corresponding receive function. If the send does not
21611629Smichael.lebeane@amd.com     * succeed, as indicated by the return value, then the sender must
21711629Smichael.lebeane@amd.com     * wait for a recvReqRetry at which point it can re-issue a
21811629Smichael.lebeane@amd.com     * sendTimingReq.
21911629Smichael.lebeane@amd.com     *
22011629Smichael.lebeane@amd.com     * @param pkt Packet to send.
22111629Smichael.lebeane@amd.com     *
22211629Smichael.lebeane@amd.com     * @return If the send was succesful or not.
22311629Smichael.lebeane@amd.com    */
22411629Smichael.lebeane@amd.com    bool sendTimingReq(PacketPtr pkt);
22511629Smichael.lebeane@amd.com
22611629Smichael.lebeane@amd.com    /**
22711629Smichael.lebeane@amd.com     * Check if the slave can handle a timing request.
22811629Smichael.lebeane@amd.com     *
22911629Smichael.lebeane@amd.com     * If the send cannot be handled at the moment, as indicated by
23011629Smichael.lebeane@amd.com     * the return value, then the sender will receive a recvReqRetry
23111629Smichael.lebeane@amd.com     * at which point it can re-issue a sendTimingReq.
23211629Smichael.lebeane@amd.com     *
23311629Smichael.lebeane@amd.com     * @param pkt Packet to send.
23411629Smichael.lebeane@amd.com     *
23511629Smichael.lebeane@amd.com     * @return If the send was succesful or not.
23611629Smichael.lebeane@amd.com     */
23711629Smichael.lebeane@amd.com    bool tryTiming(PacketPtr pkt) const;
23811629Smichael.lebeane@amd.com
23911629Smichael.lebeane@amd.com    /**
24011629Smichael.lebeane@amd.com     * Attempt to send a timing snoop response packet to the slave
24111629Smichael.lebeane@amd.com     * port by calling its corresponding receive function. If the send
24210073Sandreas@sandberg.pp.se     * does not succeed, as indicated by the return value, then the
24310073Sandreas@sandberg.pp.se     * sender must wait for a recvRetrySnoop at which point it can
24410073Sandreas@sandberg.pp.se     * re-issue a sendTimingSnoopResp.
24510073Sandreas@sandberg.pp.se     *
24610073Sandreas@sandberg.pp.se     * @param pkt Packet to send.
24710073Sandreas@sandberg.pp.se     */
24810073Sandreas@sandberg.pp.se    bool sendTimingSnoopResp(PacketPtr pkt);
24910073Sandreas@sandberg.pp.se
25010073Sandreas@sandberg.pp.se    /**
25110073Sandreas@sandberg.pp.se     * Send a retry to the slave port that previously attempted a
25210114Sandreas@sandberg.pp.se     * sendTimingResp to this master port and failed. Note that this
25310114Sandreas@sandberg.pp.se     * is virtual so that the "fake" snoop response port in the
25410098Sandreas@sandberg.pp.se     * coherent crossbar can override the behaviour.
25510098Sandreas@sandberg.pp.se     */
25610098Sandreas@sandberg.pp.se    virtual void sendRetryResp();
25710098Sandreas@sandberg.pp.se
25810073Sandreas@sandberg.pp.se    /**
25910073Sandreas@sandberg.pp.se     * Determine if this master port is snooping or not. The default
26010073Sandreas@sandberg.pp.se     * implementation returns false and thus tells the neighbour we
26110073Sandreas@sandberg.pp.se     * are not snooping. Any master port that wants to receive snoop
26210114Sandreas@sandberg.pp.se     * requests (e.g. a cache connected to a bus) has to override this
26310073Sandreas@sandberg.pp.se     * function.
26410073Sandreas@sandberg.pp.se     *
26510073Sandreas@sandberg.pp.se     * @return true if the port should be considered a snooper
26610114Sandreas@sandberg.pp.se     */
26710073Sandreas@sandberg.pp.se    virtual bool isSnooping() const { return false; }
26810073Sandreas@sandberg.pp.se
26910073Sandreas@sandberg.pp.se    /**
2709651SAndreas.Sandberg@ARM.com     * Get the address ranges of the connected slave port.
2719651SAndreas.Sandberg@ARM.com     */
2729651SAndreas.Sandberg@ARM.com    AddrRangeList getAddrRanges() const;
2739651SAndreas.Sandberg@ARM.com
2749651SAndreas.Sandberg@ARM.com    /** Inject a PrintReq for the given address to print the state of
2759651SAndreas.Sandberg@ARM.com     * that address throughout the memory system.  For debugging.
2769651SAndreas.Sandberg@ARM.com     */
2779651SAndreas.Sandberg@ARM.com    void printAddr(Addr a);
2789651SAndreas.Sandberg@ARM.com
2799684Sandreas@sandberg.pp.se  protected:
2809684Sandreas@sandberg.pp.se
2819684Sandreas@sandberg.pp.se    /**
2829684Sandreas@sandberg.pp.se     * Receive an atomic snoop request packet from the slave port.
2839684Sandreas@sandberg.pp.se     */
2849651SAndreas.Sandberg@ARM.com    virtual Tick recvAtomicSnoop(PacketPtr pkt)
2859651SAndreas.Sandberg@ARM.com    {
2869651SAndreas.Sandberg@ARM.com        panic("%s was not expecting an atomic snoop request\n", name());
2879651SAndreas.Sandberg@ARM.com        return 0;
2889651SAndreas.Sandberg@ARM.com    }
2899755Sandreas@sandberg.pp.se
2909755Sandreas@sandberg.pp.se    /**
2919755Sandreas@sandberg.pp.se     * Receive a functional snoop request packet from the slave port.
2929755Sandreas@sandberg.pp.se     */
2939755Sandreas@sandberg.pp.se    virtual void recvFunctionalSnoop(PacketPtr pkt)
2949755Sandreas@sandberg.pp.se    {
2959755Sandreas@sandberg.pp.se        panic("%s was not expecting a functional snoop request\n", name());
2969755Sandreas@sandberg.pp.se    }
2979755Sandreas@sandberg.pp.se
2989755Sandreas@sandberg.pp.se    /**
2999651SAndreas.Sandberg@ARM.com     * Receive a timing response from the slave port.
3009651SAndreas.Sandberg@ARM.com     */
3019651SAndreas.Sandberg@ARM.com    virtual bool recvTimingResp(PacketPtr pkt) = 0;
3029651SAndreas.Sandberg@ARM.com
3039651SAndreas.Sandberg@ARM.com    /**
3049651SAndreas.Sandberg@ARM.com     * Receive a timing snoop request from the slave port.
3059651SAndreas.Sandberg@ARM.com     */
3069651SAndreas.Sandberg@ARM.com    virtual void recvTimingSnoopReq(PacketPtr pkt)
3079651SAndreas.Sandberg@ARM.com    {
3089651SAndreas.Sandberg@ARM.com        panic("%s was not expecting a timing snoop request\n", name());
3099651SAndreas.Sandberg@ARM.com    }
3109651SAndreas.Sandberg@ARM.com
3119651SAndreas.Sandberg@ARM.com    /**
3129651SAndreas.Sandberg@ARM.com     * Called by the slave port if sendTimingReq was called on this
3139651SAndreas.Sandberg@ARM.com     * master port (causing recvTimingReq to be called on the slave
3149651SAndreas.Sandberg@ARM.com     * port) and was unsuccesful.
3159651SAndreas.Sandberg@ARM.com     */
3169651SAndreas.Sandberg@ARM.com    virtual void recvReqRetry() = 0;
3179651SAndreas.Sandberg@ARM.com
3189651SAndreas.Sandberg@ARM.com    /**
3199651SAndreas.Sandberg@ARM.com     * Called by the slave port if sendTimingSnoopResp was called on this
3209651SAndreas.Sandberg@ARM.com     * master port (causing recvTimingSnoopResp to be called on the slave
3219651SAndreas.Sandberg@ARM.com     * port) and was unsuccesful.
3229651SAndreas.Sandberg@ARM.com     */
3239651SAndreas.Sandberg@ARM.com    virtual void recvRetrySnoopResp()
3249651SAndreas.Sandberg@ARM.com    {
3259651SAndreas.Sandberg@ARM.com        panic("%s was not expecting a snoop retry\n", name());
3269651SAndreas.Sandberg@ARM.com    }
3279651SAndreas.Sandberg@ARM.com
3289651SAndreas.Sandberg@ARM.com    /**
3299651SAndreas.Sandberg@ARM.com     * Called to receive an address range change from the peer slave
3309651SAndreas.Sandberg@ARM.com     * port. The default implementation ignores the change and does
33110905Sandreas.sandberg@arm.com     * nothing. Override this function in a derived class if the owner
3329651SAndreas.Sandberg@ARM.com     * needs to be aware of the address ranges, e.g. in an
3339683Sandreas@sandberg.pp.se     * interconnect component like a bus.
3349683Sandreas@sandberg.pp.se     */
3359683Sandreas@sandberg.pp.se    virtual void recvRangeChange() { }
3369683Sandreas@sandberg.pp.se};
3379683Sandreas@sandberg.pp.se
3389651SAndreas.Sandberg@ARM.com/**
3399651SAndreas.Sandberg@ARM.com * A SlavePort is a specialisation of a port. In addition to the
34010905Sandreas.sandberg@arm.com * basic functionality of sending packets to its master peer, it also
3419651SAndreas.Sandberg@ARM.com * has functions specific to a slave, e.g. to send range changes
3429651SAndreas.Sandberg@ARM.com * and get the address ranges that the port responds to.
3439651SAndreas.Sandberg@ARM.com */
34410905Sandreas.sandberg@arm.comclass SlavePort : public BaseSlavePort
3459651SAndreas.Sandberg@ARM.com{
3469683Sandreas@sandberg.pp.se
3479683Sandreas@sandberg.pp.se    friend class MasterPort;
3489651SAndreas.Sandberg@ARM.com
3499651SAndreas.Sandberg@ARM.com  private:
35010905Sandreas.sandberg@arm.com
3519652SAndreas.Sandberg@ARM.com    MasterPort* _masterPort;
3529651SAndreas.Sandberg@ARM.com
3539651SAndreas.Sandberg@ARM.com  public:
35410913Sandreas.sandberg@arm.com
35510913Sandreas.sandberg@arm.com    SlavePort(const std::string& name, MemObject* owner,
3569651SAndreas.Sandberg@ARM.com              PortID id = InvalidPortID);
3579651SAndreas.Sandberg@ARM.com    virtual ~SlavePort();
35810913Sandreas.sandberg@arm.com
3599651SAndreas.Sandberg@ARM.com    /**
3609753Sandreas@sandberg.pp.se     * Send an atomic snoop request packet, where the data is moved
3619753Sandreas@sandberg.pp.se     * and the state is updated in zero time, without interleaving
3629753Sandreas@sandberg.pp.se     * with other memory accesses.
3639753Sandreas@sandberg.pp.se     *
3649753Sandreas@sandberg.pp.se     * @param pkt Snoop packet to send.
3659753Sandreas@sandberg.pp.se     *
3669753Sandreas@sandberg.pp.se     * @return Estimated latency of access.
3679753Sandreas@sandberg.pp.se     */
36810913Sandreas.sandberg@arm.com    Tick sendAtomicSnoop(PacketPtr pkt);
36910913Sandreas.sandberg@arm.com
3709651SAndreas.Sandberg@ARM.com    /**
3719753Sandreas@sandberg.pp.se     * Send a functional snoop request packet, where the data is
3729753Sandreas@sandberg.pp.se     * instantly updated everywhere in the memory system, without
3739753Sandreas@sandberg.pp.se     * affecting the current state of any block or moving the block.
3749753Sandreas@sandberg.pp.se     *
3759753Sandreas@sandberg.pp.se     * @param pkt Snoop packet to send.
3769753Sandreas@sandberg.pp.se     */
3779753Sandreas@sandberg.pp.se    void sendFunctionalSnoop(PacketPtr pkt);
3789651SAndreas.Sandberg@ARM.com
3799753Sandreas@sandberg.pp.se    /**
3809753Sandreas@sandberg.pp.se     * Attempt to send a timing response to the master port by calling
3819753Sandreas@sandberg.pp.se     * its corresponding receive function. If the send does not
3829753Sandreas@sandberg.pp.se     * succeed, as indicated by the return value, then the sender must
3839753Sandreas@sandberg.pp.se     * wait for a recvRespRetry at which point it can re-issue a
3849753Sandreas@sandberg.pp.se     * sendTimingResp.
3859753Sandreas@sandberg.pp.se     *
3869753Sandreas@sandberg.pp.se     * @param pkt Packet to send.
3879753Sandreas@sandberg.pp.se     *
38810913Sandreas.sandberg@arm.com     * @return If the send was succesful or not.
3899753Sandreas@sandberg.pp.se    */
3909753Sandreas@sandberg.pp.se    bool sendTimingResp(PacketPtr pkt);
3919753Sandreas@sandberg.pp.se
3929753Sandreas@sandberg.pp.se    /**
3939753Sandreas@sandberg.pp.se     * Attempt to send a timing snoop request packet to the master port
3949753Sandreas@sandberg.pp.se     * by calling its corresponding receive function. Snoop requests
3959753Sandreas@sandberg.pp.se     * always succeed and hence no return value is needed.
3969753Sandreas@sandberg.pp.se     *
3979753Sandreas@sandberg.pp.se     * @param pkt Packet to send.
3989753Sandreas@sandberg.pp.se     */
39910913Sandreas.sandberg@arm.com    void sendTimingSnoopReq(PacketPtr pkt);
4009753Sandreas@sandberg.pp.se
40111629Smichael.lebeane@amd.com    /**
40211629Smichael.lebeane@amd.com     * Send a retry to the master port that previously attempted a
40311629Smichael.lebeane@amd.com     * sendTimingReq to this slave port and failed.
40411629Smichael.lebeane@amd.com     */
40511629Smichael.lebeane@amd.com    void sendRetryReq();
40611629Smichael.lebeane@amd.com
4079753Sandreas@sandberg.pp.se    /**
4089753Sandreas@sandberg.pp.se     * Send a retry to the master port that previously attempted a
4099753Sandreas@sandberg.pp.se     * sendTimingSnoopResp to this slave port and failed.
41010913Sandreas.sandberg@arm.com     */
4119753Sandreas@sandberg.pp.se    void sendRetrySnoopResp();
4129753Sandreas@sandberg.pp.se
4139753Sandreas@sandberg.pp.se    /**
41410913Sandreas.sandberg@arm.com     * Find out if the peer master port is snooping or not.
4159753Sandreas@sandberg.pp.se     *
4169651SAndreas.Sandberg@ARM.com     * @return true if the peer master port is snooping
4179651SAndreas.Sandberg@ARM.com     */
4189651SAndreas.Sandberg@ARM.com    bool isSnooping() const { return _masterPort->isSnooping(); }
4199651SAndreas.Sandberg@ARM.com
4209651SAndreas.Sandberg@ARM.com    /**
4219651SAndreas.Sandberg@ARM.com     * Called by the owner to send a range change
4229651SAndreas.Sandberg@ARM.com     */
4239651SAndreas.Sandberg@ARM.com    void sendRangeChange() const {
4249651SAndreas.Sandberg@ARM.com        if (!_masterPort)
4259651SAndreas.Sandberg@ARM.com            fatal("%s cannot sendRangeChange() without master port", name());
4269651SAndreas.Sandberg@ARM.com        _masterPort->recvRangeChange();
4279651SAndreas.Sandberg@ARM.com    }
4289651SAndreas.Sandberg@ARM.com
4299651SAndreas.Sandberg@ARM.com    /**
4309651SAndreas.Sandberg@ARM.com     * Get a list of the non-overlapping address ranges the owner is
4319651SAndreas.Sandberg@ARM.com     * responsible for. All slave ports must override this function
4329651SAndreas.Sandberg@ARM.com     * and return a populated list with at least one item.
4339651SAndreas.Sandberg@ARM.com     *
4349651SAndreas.Sandberg@ARM.com     * @return a list of ranges responded to
4359651SAndreas.Sandberg@ARM.com     */
4369651SAndreas.Sandberg@ARM.com    virtual AddrRangeList getAddrRanges() const = 0;
4379651SAndreas.Sandberg@ARM.com
4389651SAndreas.Sandberg@ARM.com  protected:
4399651SAndreas.Sandberg@ARM.com
4409651SAndreas.Sandberg@ARM.com    /**
4419651SAndreas.Sandberg@ARM.com     * Called by the master port to unbind. Should never be called
44211363Sandreas@sandberg.pp.se     * directly.
44311363Sandreas@sandberg.pp.se     */
44411363Sandreas@sandberg.pp.se    void unbind();
44511363Sandreas@sandberg.pp.se
44611363Sandreas@sandberg.pp.se    /**
44711363Sandreas@sandberg.pp.se     * Called by the master port to bind. Should never be called
44811363Sandreas@sandberg.pp.se     * directly.
44911363Sandreas@sandberg.pp.se     */
45011363Sandreas@sandberg.pp.se    void bind(MasterPort& master_port);
45111363Sandreas@sandberg.pp.se
45211363Sandreas@sandberg.pp.se    /**
45311363Sandreas@sandberg.pp.se     * Receive an atomic request packet from the master port.
45411363Sandreas@sandberg.pp.se     */
45511363Sandreas@sandberg.pp.se    virtual Tick recvAtomic(PacketPtr pkt) = 0;
45611363Sandreas@sandberg.pp.se
45711363Sandreas@sandberg.pp.se    /**
45811363Sandreas@sandberg.pp.se     * Receive a functional request packet from the master port.
45911363Sandreas@sandberg.pp.se     */
46011363Sandreas@sandberg.pp.se    virtual void recvFunctional(PacketPtr pkt) = 0;
46111363Sandreas@sandberg.pp.se
46211363Sandreas@sandberg.pp.se    /**
46311363Sandreas@sandberg.pp.se     * Receive a timing request from the master port.
46411363Sandreas@sandberg.pp.se     */
4659651SAndreas.Sandberg@ARM.com    virtual bool recvTimingReq(PacketPtr pkt) = 0;
4669651SAndreas.Sandberg@ARM.com
4679652SAndreas.Sandberg@ARM.com    /**
4689652SAndreas.Sandberg@ARM.com     * Availability request from the master port.
4699651SAndreas.Sandberg@ARM.com     */
4709651SAndreas.Sandberg@ARM.com    virtual bool tryTiming(PacketPtr pkt) {
4719651SAndreas.Sandberg@ARM.com        panic("%s was not expecting a %s\n", name(), __func__);
4729651SAndreas.Sandberg@ARM.com    }
4739651SAndreas.Sandberg@ARM.com
4749651SAndreas.Sandberg@ARM.com    /**
4759651SAndreas.Sandberg@ARM.com     * Receive a timing snoop response from the master port.
4769651SAndreas.Sandberg@ARM.com     */
4779651SAndreas.Sandberg@ARM.com    virtual bool recvTimingSnoopResp(PacketPtr pkt)
4789651SAndreas.Sandberg@ARM.com    {
4799651SAndreas.Sandberg@ARM.com        panic("%s was not expecting a timing snoop response\n", name());
4809651SAndreas.Sandberg@ARM.com    }
4819651SAndreas.Sandberg@ARM.com
4829651SAndreas.Sandberg@ARM.com    /**
4839651SAndreas.Sandberg@ARM.com     * Called by the master port if sendTimingResp was called on this
4849651SAndreas.Sandberg@ARM.com     * slave port (causing recvTimingResp to be called on the master
4859651SAndreas.Sandberg@ARM.com     * port) and was unsuccesful.
4869651SAndreas.Sandberg@ARM.com     */
4879651SAndreas.Sandberg@ARM.com    virtual void recvRespRetry() = 0;
4889651SAndreas.Sandberg@ARM.com
4899651SAndreas.Sandberg@ARM.com};
4909651SAndreas.Sandberg@ARM.com
4919651SAndreas.Sandberg@ARM.com#endif //__MEM_PORT_HH__
4929753Sandreas@sandberg.pp.se