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