port.hh revision 12342
12810SN/A/*
22810SN/A * Copyright (c) 2011-2012,2015,2017 ARM Limited
37636Ssteve.reinhardt@amd.com * All rights reserved
42810SN/A *
52810SN/A * The license below extends only to copyright in the software and shall
62810SN/A * not be construed as granting a license to any other intellectual
72810SN/A * property including but not limited to intellectual property relating
82810SN/A * to a hardware implementation of the functionality of the software
92810SN/A * licensed hereunder.  You may use the software subject to the license
102810SN/A * terms below provided that you ensure that this notice is replicated
112810SN/A * unmodified and in its entirety in all distributions of the software,
122810SN/A * modified or unmodified, in source code or in binary form.
132810SN/A *
142810SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
152810SN/A * All rights reserved.
162810SN/A *
172810SN/A * Redistribution and use in source and binary forms, with or without
182810SN/A * modification, are permitted provided that the following conditions are
192810SN/A * met: redistributions of source code must retain the above copyright
202810SN/A * notice, this list of conditions and the following disclaimer;
212810SN/A * redistributions in binary form must reproduce the above copyright
222810SN/A * notice, this list of conditions and the following disclaimer in the
232810SN/A * documentation and/or other materials provided with the distribution;
242810SN/A * neither the name of the copyright holders nor the names of its
252810SN/A * contributors may be used to endorse or promote products derived from
262810SN/A * this software without specific prior written permission.
272810SN/A *
282810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
386216Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
396216Snate@binkert.org *
402810SN/A * Authors: Ron Dreslinski
412810SN/A *          Andreas Hansson
422810SN/A *          William Wang
436216Snate@binkert.org */
446216Snate@binkert.org
458232Snate@binkert.org/**
466216Snate@binkert.org * @file
475338Sstever@gmail.com * Port Object Declaration.
486216Snate@binkert.org */
492810SN/A
502810SN/A#ifndef __MEM_PORT_HH__
512810SN/A#define __MEM_PORT_HH__
522810SN/A
532810SN/A#include "base/addr_range.hh"
542810SN/A#include "mem/packet.hh"
552810SN/A
566221Snate@binkert.orgclass MemObject;
574903SN/A
584903SN/A/**
592810SN/A * Ports are used to interface memory objects to each other. A port is
602810SN/A * either a master or a slave and the connected peer is always of the
614903SN/A * opposite role. Each port has a name, an owner, and an identifier.
624903SN/A */
634903SN/Aclass Port
644903SN/A{
654903SN/A
664903SN/A  private:
674903SN/A
684908SN/A    /** Descriptive name (for DPRINTF output) */
695875Ssteve.reinhardt@amd.com    std::string portName;
704903SN/A
715875Ssteve.reinhardt@amd.com  protected:
724903SN/A
734903SN/A    /**
744903SN/A     * A numeric identifier to distinguish ports in a vector, and set
754903SN/A     * to InvalidPortID in case this port is not part of a vector.
767669Ssteve.reinhardt@amd.com     */
777669Ssteve.reinhardt@amd.com    const PortID id;
787669Ssteve.reinhardt@amd.com
797669Ssteve.reinhardt@amd.com    /** A reference to the MemObject that owns this port. */
804903SN/A    MemObject& owner;
814903SN/A
825318SN/A    /**
834908SN/A     * Abstract base class for ports
845318SN/A     *
859543Ssascha.bischoff@arm.com     * @param _name Port name including the owners name
869543Ssascha.bischoff@arm.com     * @param _owner The MemObject that is the structural owner of this port
879543Ssascha.bischoff@arm.com     * @param _id A port identifier for vector ports
889543Ssascha.bischoff@arm.com     */
894908SN/A    Port(const std::string& _name, MemObject& _owner, PortID _id);
904908SN/A
914908SN/A    /**
924908SN/A     * Virtual destructor due to inheritance.
934903SN/A     */
944903SN/A    virtual ~Port();
955875Ssteve.reinhardt@amd.com
964903SN/A  public:
974903SN/A
984903SN/A    /** Return port name (for DPRINTF). */
997667Ssteve.reinhardt@amd.com    const std::string name() const { return portName; }
1007667Ssteve.reinhardt@amd.com
1017667Ssteve.reinhardt@amd.com    /** Get the port id. */
1027667Ssteve.reinhardt@amd.com    PortID getId() const { return id; }
1037667Ssteve.reinhardt@amd.com
1047667Ssteve.reinhardt@amd.com};
1057667Ssteve.reinhardt@amd.com
1067667Ssteve.reinhardt@amd.com/** Forward declaration */
1077667Ssteve.reinhardt@amd.comclass BaseSlavePort;
1087669Ssteve.reinhardt@amd.com
1097669Ssteve.reinhardt@amd.com/**
1107669Ssteve.reinhardt@amd.com * A BaseMasterPort is a protocol-agnostic master port, responsible
1117667Ssteve.reinhardt@amd.com * only for the structural connection to a slave port. The final
1127667Ssteve.reinhardt@amd.com * master port that inherits from the base class must override the
1137667Ssteve.reinhardt@amd.com * bind member function for the specific slave port class.
1147667Ssteve.reinhardt@amd.com */
1154903SN/Aclass BaseMasterPort : public Port
1164903SN/A{
1174903SN/A
1184903SN/A  protected:
1194903SN/A
1204903SN/A    BaseSlavePort* _baseSlavePort;
1214903SN/A
1224903SN/A    BaseMasterPort(const std::string& name, MemObject* owner,
1237667Ssteve.reinhardt@amd.com                   PortID id = InvalidPortID);
1244903SN/A    virtual ~BaseMasterPort();
1254903SN/A
1264903SN/A  public:
1274903SN/A
1284903SN/A    virtual void bind(BaseSlavePort& slave_port) = 0;
1294903SN/A    virtual void unbind() = 0;
1302810SN/A    BaseSlavePort& getSlavePort() const;
1314908SN/A    bool isConnected() const;
1324908SN/A
1334908SN/A};
1344908SN/A
1355318SN/A/**
1369543Ssascha.bischoff@arm.com * A BaseSlavePort is a protocol-agnostic slave port, responsible
1379543Ssascha.bischoff@arm.com * only for the structural connection to a master port.
1389543Ssascha.bischoff@arm.com */
1399543Ssascha.bischoff@arm.comclass BaseSlavePort : public Port
1409543Ssascha.bischoff@arm.com{
1419543Ssascha.bischoff@arm.com
1429543Ssascha.bischoff@arm.com  protected:
1435318SN/A
1445318SN/A    BaseMasterPort* _baseMasterPort;
1455318SN/A
1464908SN/A    BaseSlavePort(const std::string& name, MemObject* owner,
1474908SN/A                  PortID id = InvalidPortID);
1484908SN/A    virtual ~BaseSlavePort();
1494908SN/A
1504908SN/A  public:
1514920SN/A
1524920SN/A    BaseMasterPort& getMasterPort() const;
1534920SN/A    bool isConnected() const;
1544920SN/A
1554920SN/A};
1564920SN/A
1574920SN/A/** Forward declaration */
1584920SN/Aclass SlavePort;
1594920SN/A
1604920SN/A/**
1614920SN/A * A MasterPort is a specialisation of a BaseMasterPort, which
1624920SN/A * implements the default protocol for the three different level of
1634920SN/A * transport functions. In addition to the basic functionality of
1644920SN/A * sending packets, it also has functions to receive range changes or
1654908SN/A * determine if the port is snooping or not.
1665314SN/A */
1675314SN/Aclass MasterPort : public BaseMasterPort
1685314SN/A{
1695314SN/A
1705314SN/A    friend class SlavePort;
1715875Ssteve.reinhardt@amd.com
1725875Ssteve.reinhardt@amd.com  private:
1738988SAli.Saidi@ARM.com
1748988SAli.Saidi@ARM.com    SlavePort* _slavePort;
1758988SAli.Saidi@ARM.com
1768988SAli.Saidi@ARM.com  public:
1778988SAli.Saidi@ARM.com
1788988SAli.Saidi@ARM.com    MasterPort(const std::string& name, MemObject* owner,
1798988SAli.Saidi@ARM.com               PortID id = InvalidPortID);
1808988SAli.Saidi@ARM.com    virtual ~MasterPort();
1818988SAli.Saidi@ARM.com
1828988SAli.Saidi@ARM.com    /**
1838988SAli.Saidi@ARM.com     * Bind this master port to a slave port. This also does the
1848988SAli.Saidi@ARM.com     * mirror action and binds the slave port to the master port.
1855875Ssteve.reinhardt@amd.com     */
1865875Ssteve.reinhardt@amd.com    void bind(BaseSlavePort& slave_port);
1875314SN/A
1885314SN/A    /**
1895314SN/A     * Unbind this master port and the associated slave port.
1905314SN/A     */
1915314SN/A    void unbind();
1925314SN/A
1934666SN/A    /**
1944871SN/A     * Send an atomic request packet, where the data is moved and the
1952810SN/A     * state is updated in zero time, without interleaving with other
1962885SN/A     * memory accesses.
1974626SN/A     *
1984871SN/A     * @param pkt Packet to send.
1994666SN/A     *
2004626SN/A     * @return Estimated latency of access.
2015730SSteve.Reinhardt@amd.com     */
2024626SN/A    Tick sendAtomic(PacketPtr pkt);
2034626SN/A
2044908SN/A    /**
2054626SN/A     * Send a functional request packet, where the data is instantly
2064626SN/A     * updated everywhere in the memory system, without affecting the
2075875Ssteve.reinhardt@amd.com     * current state of any block or moving the block.
2084626SN/A     *
2095875Ssteve.reinhardt@amd.com     * @param pkt Packet to send.
2105875Ssteve.reinhardt@amd.com     */
2115875Ssteve.reinhardt@amd.com    void sendFunctional(PacketPtr pkt);
2125875Ssteve.reinhardt@amd.com
2134903SN/A    /**
2144668SN/A     * Attempt to send a timing request to the slave port by calling
2152810SN/A     * its corresponding receive function. If the send does not
2162810SN/A     * succeed, as indicated by the return value, then the sender must
2174908SN/A     * wait for a recvReqRetry at which point it can re-issue a
2185318SN/A     * sendTimingReq.
2195318SN/A     *
2205318SN/A     * @param pkt Packet to send.
2215318SN/A     *
2225318SN/A     * @return If the send was succesful or not.
2235318SN/A    */
2245318SN/A    bool sendTimingReq(PacketPtr pkt);
2255318SN/A
2265318SN/A    /**
2275318SN/A     * Check if the slave can handle a timing request.
2284908SN/A     *
2297667Ssteve.reinhardt@amd.com     * If the send cannot be handled at the moment, as indicated by
2304908SN/A     * the return value, then the sender will receive a recvReqRetry
2314908SN/A     * at which point it can re-issue a sendTimingReq.
2325730SSteve.Reinhardt@amd.com     *
2334908SN/A     * @param pkt Packet to send.
2344908SN/A     *
2354908SN/A     * @return If the send was succesful or not.
2364908SN/A     */
2374908SN/A    bool tryTiming(PacketPtr pkt) const;
2384908SN/A
2394908SN/A    /**
2407667Ssteve.reinhardt@amd.com     * Attempt to send a timing snoop response packet to the slave
2417667Ssteve.reinhardt@amd.com     * port by calling its corresponding receive function. If the send
2427667Ssteve.reinhardt@amd.com     * does not succeed, as indicated by the return value, then the
2437667Ssteve.reinhardt@amd.com     * sender must wait for a recvRetrySnoop at which point it can
2444908SN/A     * re-issue a sendTimingSnoopResp.
2454908SN/A     *
2464908SN/A     * @param pkt Packet to send.
2474908SN/A     */
2484908SN/A    bool sendTimingSnoopResp(PacketPtr pkt);
2494908SN/A
2504908SN/A    /**
2514908SN/A     * Send a retry to the slave port that previously attempted a
2524908SN/A     * sendTimingResp to this master port and failed. Note that this
2532810SN/A     * is virtual so that the "fake" snoop response port in the
2542810SN/A     * coherent crossbar can override the behaviour.
2552810SN/A     */
2564903SN/A    virtual void sendRetryResp();
2574903SN/A
2584903SN/A    /**
2592810SN/A     * Determine if this master port is snooping or not. The default
2602810SN/A     * implementation returns false and thus tells the neighbour we
2612810SN/A     * are not snooping. Any master port that wants to receive snoop
2622810SN/A     * requests (e.g. a cache connected to a bus) has to override this
2632810SN/A     * function.
2642810SN/A     *
2652810SN/A     * @return true if the port should be considered a snooper
2662810SN/A     */
2674903SN/A    virtual bool isSnooping() const { return false; }
2682810SN/A
2694903SN/A    /**
2704903SN/A     * Get the address ranges of the connected slave port.
2714903SN/A     */
2724903SN/A    AddrRangeList getAddrRanges() const;
2734903SN/A
2744903SN/A    /** Inject a PrintReq for the given address to print the state of
2757667Ssteve.reinhardt@amd.com     * that address throughout the memory system.  For debugging.
2767667Ssteve.reinhardt@amd.com     */
2777667Ssteve.reinhardt@amd.com    void printAddr(Addr a);
2787667Ssteve.reinhardt@amd.com
2795875Ssteve.reinhardt@amd.com  protected:
2805875Ssteve.reinhardt@amd.com
2815875Ssteve.reinhardt@amd.com    /**
2825875Ssteve.reinhardt@amd.com     * Receive an atomic snoop request packet from the slave port.
2835875Ssteve.reinhardt@amd.com     */
2844903SN/A    virtual Tick recvAtomicSnoop(PacketPtr pkt)
2857667Ssteve.reinhardt@amd.com    {
2867667Ssteve.reinhardt@amd.com        panic("%s was not expecting an atomic snoop request\n", name());
2877667Ssteve.reinhardt@amd.com        return 0;
2884903SN/A    }
2897667Ssteve.reinhardt@amd.com
2907667Ssteve.reinhardt@amd.com    /**
2915875Ssteve.reinhardt@amd.com     * Receive a functional snoop request packet from the slave port.
2924665SN/A     */
2935318SN/A    virtual void recvFunctionalSnoop(PacketPtr pkt)
2945318SN/A    {
2955318SN/A        panic("%s was not expecting a functional snoop request\n", name());
2965318SN/A    }
2975875Ssteve.reinhardt@amd.com
2982810SN/A    /**
2992810SN/A     * Receive a timing response from the slave port.
3002810SN/A     */
3014665SN/A    virtual bool recvTimingResp(PacketPtr pkt) = 0;
3024665SN/A
3034902SN/A    /**
3044902SN/A     * Receive a timing snoop request from the slave port.
3054665SN/A     */
3064910SN/A    virtual void recvTimingSnoopReq(PacketPtr pkt)
3074903SN/A    {
3084903SN/A        panic("%s was not expecting a timing snoop request\n", name());
3094903SN/A    }
3104903SN/A
3114903SN/A    /**
3124903SN/A     * Called by the slave port if sendTimingReq was called on this
3134903SN/A     * master port (causing recvTimingReq to be called on the slave
3144903SN/A     * port) and was unsuccesful.
3154903SN/A     */
3164903SN/A    virtual void recvReqRetry() = 0;
3174903SN/A
3184903SN/A    /**
3194903SN/A     * Called by the slave port if sendTimingSnoopResp was called on this
3204903SN/A     * master port (causing recvTimingSnoopResp to be called on the slave
3214903SN/A     * port) and was unsuccesful.
3224903SN/A     */
3234903SN/A    virtual void recvRetrySnoopResp()
3244903SN/A    {
3254902SN/A        panic("%s was not expecting a snoop retry\n", name());
3264902SN/A    }
3274665SN/A
3284903SN/A    /**
3294903SN/A     * Called to receive an address range change from the peer slave
3304903SN/A     * port. The default implementation ignores the change and does
3314903SN/A     * nothing. Override this function in a derived class if the owner
3324903SN/A     * needs to be aware of the address ranges, e.g. in an
3334903SN/A     * interconnect component like a bus.
3344903SN/A     */
3354903SN/A    virtual void recvRangeChange() { }
3367667Ssteve.reinhardt@amd.com};
3374665SN/A
3384903SN/A/**
3394903SN/A * A SlavePort is a specialisation of a port. In addition to the
3404902SN/A * basic functionality of sending packets to its master peer, it also
3414665SN/A * has functions specific to a slave, e.g. to send range changes
3424665SN/A * and get the address ranges that the port responds to.
3437667Ssteve.reinhardt@amd.com */
3447667Ssteve.reinhardt@amd.comclass SlavePort : public BaseSlavePort
3457667Ssteve.reinhardt@amd.com{
3467667Ssteve.reinhardt@amd.com
3477667Ssteve.reinhardt@amd.com    friend class MasterPort;
3487667Ssteve.reinhardt@amd.com
3497667Ssteve.reinhardt@amd.com  private:
3507667Ssteve.reinhardt@amd.com
3518931Sandreas.hansson@arm.com    MasterPort* _masterPort;
3527667Ssteve.reinhardt@amd.com
3534970SN/A  public:
3547823Ssteve.reinhardt@amd.com
3555318SN/A    SlavePort(const std::string& name, MemObject* owner,
3564670SN/A              PortID id = InvalidPortID);
3574670SN/A    virtual ~SlavePort();
3587667Ssteve.reinhardt@amd.com
3594670SN/A    /**
3604916SN/A     * Send an atomic snoop request packet, where the data is moved
3614670SN/A     * and the state is updated in zero time, without interleaving
3624670SN/A     * with other memory accesses.
3634670SN/A     *
3644670SN/A     * @param pkt Snoop packet to send.
3657667Ssteve.reinhardt@amd.com     *
3664670SN/A     * @return Estimated latency of access.
3677667Ssteve.reinhardt@amd.com     */
3687667Ssteve.reinhardt@amd.com    Tick sendAtomicSnoop(PacketPtr pkt);
3697667Ssteve.reinhardt@amd.com
3707667Ssteve.reinhardt@amd.com    /**
3717667Ssteve.reinhardt@amd.com     * Send a functional snoop request packet, where the data is
3727667Ssteve.reinhardt@amd.com     * instantly updated everywhere in the memory system, without
3734670SN/A     * affecting the current state of any block or moving the block.
3744667SN/A     *
3754902SN/A     * @param pkt Snoop packet to send.
3764902SN/A     */
3774665SN/A    void sendFunctionalSnoop(PacketPtr pkt);
3784665SN/A
3794665SN/A    /**
3804665SN/A     * Attempt to send a timing response to the master port by calling
3814665SN/A     * its corresponding receive function. If the send does not
3824665SN/A     * succeed, as indicated by the return value, then the sender must
3834903SN/A     * wait for a recvRespRetry at which point it can re-issue a
3844903SN/A     * sendTimingResp.
3854665SN/A     *
3864665SN/A     * @param pkt Packet to send.
3874665SN/A     *
3884903SN/A     * @return If the send was succesful or not.
3894903SN/A    */
3904665SN/A    bool sendTimingResp(PacketPtr pkt);
3914903SN/A
3922810SN/A    /**
3934903SN/A     * Attempt to send a timing snoop request packet to the master port
3944903SN/A     * by calling its corresponding receive function. Snoop requests
3954903SN/A     * always succeed and hence no return value is needed.
3964903SN/A     *
3974903SN/A     * @param pkt Packet to send.
3984903SN/A     */
3997823Ssteve.reinhardt@amd.com    void sendTimingSnoopReq(PacketPtr pkt);
4004665SN/A
4014665SN/A    /**
4022810SN/A     * Send a retry to the master port that previously attempted a
4032810SN/A     * sendTimingReq to this slave port and failed.
4042810SN/A     */
4052810SN/A    void sendRetryReq();
4064670SN/A
4074668SN/A    /**
4087667Ssteve.reinhardt@amd.com     * Send a retry to the master port that previously attempted a
4097667Ssteve.reinhardt@amd.com     * sendTimingSnoopResp to this slave port and failed.
4105270SN/A     */
4115270SN/A    void sendRetrySnoopResp();
4125270SN/A
4135270SN/A    /**
4145270SN/A     * Find out if the peer master port is snooping or not.
4155270SN/A     *
4165270SN/A     * @return true if the peer master port is snooping
4175270SN/A     */
4185270SN/A    bool isSnooping() const { return _masterPort->isSnooping(); }
4195270SN/A
4205270SN/A    /**
4215318SN/A     * Called by the owner to send a range change
4225318SN/A     */
4235318SN/A    void sendRangeChange() const {
4245318SN/A        if (!_masterPort)
4255270SN/A            fatal("%s cannot sendRangeChange() without master port", name());
4265270SN/A        _masterPort->recvRangeChange();
4275270SN/A    }
4285270SN/A
4294668SN/A    /**
4304668SN/A     * Get a list of the non-overlapping address ranges the owner is
4314668SN/A     * responsible for. All slave ports must override this function
4325314SN/A     * and return a populated list with at least one item.
4335314SN/A     *
4345314SN/A     * @return a list of ranges responded to
4355314SN/A     */
4365314SN/A    virtual AddrRangeList getAddrRanges() const = 0;
4375314SN/A
4385314SN/A  protected:
4395314SN/A
4405314SN/A    /**
4415314SN/A     * Called by the master port to unbind. Should never be called
4425314SN/A     * directly.
4435314SN/A     */
4445314SN/A    void unbind();
4455314SN/A
4465314SN/A    /**
4475314SN/A     * Called by the master port to bind. Should never be called
4484668SN/A     * directly.
4495314SN/A     */
4502810SN/A    void bind(MasterPort& master_port);
4515314SN/A
4525314SN/A    /**
4535730SSteve.Reinhardt@amd.com     * Receive an atomic request packet from the master port.
4545730SSteve.Reinhardt@amd.com     */
4555314SN/A    virtual Tick recvAtomic(PacketPtr pkt) = 0;
4565314SN/A
4575314SN/A    /**
4585314SN/A     * Receive a functional request packet from the master port.
4597667Ssteve.reinhardt@amd.com     */
4607667Ssteve.reinhardt@amd.com    virtual void recvFunctional(PacketPtr pkt) = 0;
4612810SN/A
4625314SN/A    /**
4635314SN/A     * Receive a timing request from the master port.
4645314SN/A     */
4655314SN/A    virtual bool recvTimingReq(PacketPtr pkt) = 0;
4665314SN/A
4672810SN/A    /**
4682810SN/A     * Availability request from the master port.
4692810SN/A     */
4702810SN/A    virtual bool tryTiming(PacketPtr pkt) {
4712810SN/A        panic("%s was not expecting a %s\n", name(), __func__);
4729086Sandreas.hansson@arm.com    }
4739086Sandreas.hansson@arm.com
4742810SN/A    /**
475     * Receive a timing snoop response from the master port.
476     */
477    virtual bool recvTimingSnoopResp(PacketPtr pkt)
478    {
479        panic("%s was not expecting a timing snoop response\n", name());
480    }
481
482    /**
483     * Called by the master port if sendTimingResp was called on this
484     * slave port (causing recvTimingResp to be called on the master
485     * port) and was unsuccesful.
486     */
487    virtual void recvRespRetry() = 0;
488
489};
490
491#endif //__MEM_PORT_HH__
492