port.hh revision 13892
14403Srdreslin@umich.edu/*
21693Sstever@eecs.umich.edu * Copyright (c) 2011-2012,2015,2017 ARM Limited
31693Sstever@eecs.umich.edu * All rights reserved
41693Sstever@eecs.umich.edu *
51693Sstever@eecs.umich.edu * The license below extends only to copyright in the software and shall
61693Sstever@eecs.umich.edu * not be construed as granting a license to any other intellectual
71693Sstever@eecs.umich.edu * property including but not limited to intellectual property relating
81693Sstever@eecs.umich.edu * to a hardware implementation of the functionality of the software
91693Sstever@eecs.umich.edu * licensed hereunder.  You may use the software subject to the license
101693Sstever@eecs.umich.edu * terms below provided that you ensure that this notice is replicated
111693Sstever@eecs.umich.edu * unmodified and in its entirety in all distributions of the software,
121693Sstever@eecs.umich.edu * modified or unmodified, in source code or in binary form.
131693Sstever@eecs.umich.edu *
141693Sstever@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan
151693Sstever@eecs.umich.edu * All rights reserved.
161693Sstever@eecs.umich.edu *
171693Sstever@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
181693Sstever@eecs.umich.edu * modification, are permitted provided that the following conditions are
191693Sstever@eecs.umich.edu * met: redistributions of source code must retain the above copyright
201693Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
211693Sstever@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
221693Sstever@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
231693Sstever@eecs.umich.edu * documentation and/or other materials provided with the distribution;
241693Sstever@eecs.umich.edu * neither the name of the copyright holders nor the names of its
251693Sstever@eecs.umich.edu * contributors may be used to endorse or promote products derived from
261693Sstever@eecs.umich.edu * this software without specific prior written permission.
271693Sstever@eecs.umich.edu *
281693Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
293358Srdreslin@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
303358Srdreslin@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
311516SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
326654Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
336654Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
346654Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
356654Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
363358Srdreslin@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
373358Srdreslin@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
386654Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
396654Snate@binkert.org *
401516SN/A * Authors: Ron Dreslinski
413358Srdreslin@umich.edu *          Andreas Hansson
423358Srdreslin@umich.edu *          William Wang
433358Srdreslin@umich.edu */
443358Srdreslin@umich.edu
453358Srdreslin@umich.edu/**
463358Srdreslin@umich.edu * @file
473358Srdreslin@umich.edu * Port Object Declaration.
483358Srdreslin@umich.edu */
493358Srdreslin@umich.edu
503358Srdreslin@umich.edu#ifndef __MEM_PORT_HH__
513358Srdreslin@umich.edu#define __MEM_PORT_HH__
523358Srdreslin@umich.edu
533360Srdreslin@umich.edu#include "base/addr_range.hh"
543358Srdreslin@umich.edu#include "mem/backdoor.hh"
553360Srdreslin@umich.edu#include "mem/packet.hh"
563360Srdreslin@umich.edu#include "sim/port.hh"
573360Srdreslin@umich.edu
585255Ssaidi@eecs.umich.educlass SimObject;
593360Srdreslin@umich.edu
603360Srdreslin@umich.edu/** Forward declaration */
613360Srdreslin@umich.educlass BaseSlavePort;
625255Ssaidi@eecs.umich.edu
633358Srdreslin@umich.edu/**
644403Srdreslin@umich.edu * A BaseMasterPort is a protocol-agnostic master port, responsible
653360Srdreslin@umich.edu * only for the structural connection to a slave port. The final
663358Srdreslin@umich.edu * master port that inherits from the base class must override the
673358Srdreslin@umich.edu * bind member function for the specific slave port class.
683358Srdreslin@umich.edu */
693358Srdreslin@umich.educlass BaseMasterPort : public Port
703358Srdreslin@umich.edu{
713358Srdreslin@umich.edu
723358Srdreslin@umich.edu  protected:
733358Srdreslin@umich.edu
743358Srdreslin@umich.edu    BaseSlavePort* _baseSlavePort;
753360Srdreslin@umich.edu
763360Srdreslin@umich.edu    BaseMasterPort(const std::string& name, PortID id=InvalidPortID);
773360Srdreslin@umich.edu    virtual ~BaseMasterPort();
783360Srdreslin@umich.edu
793358Srdreslin@umich.edu  public:
803358Srdreslin@umich.edu
813358Srdreslin@umich.edu    BaseSlavePort& getSlavePort() const;
823358Srdreslin@umich.edu
834403Srdreslin@umich.edu};
844403Srdreslin@umich.edu
855256Ssaidi@eecs.umich.edu/**
865255Ssaidi@eecs.umich.edu * A BaseSlavePort is a protocol-agnostic slave port, responsible
873358Srdreslin@umich.edu * only for the structural connection to a master port.
883358Srdreslin@umich.edu */
894403Srdreslin@umich.educlass BaseSlavePort : public Port
904403Srdreslin@umich.edu{
915255Ssaidi@eecs.umich.edu
923358Srdreslin@umich.edu  protected:
933358Srdreslin@umich.edu
944403Srdreslin@umich.edu    BaseMasterPort* _baseMasterPort;
955255Ssaidi@eecs.umich.edu
964403Srdreslin@umich.edu    BaseSlavePort(const std::string& name, PortID id=InvalidPortID);
973358Srdreslin@umich.edu    virtual ~BaseSlavePort();
983358Srdreslin@umich.edu
994403Srdreslin@umich.edu  public:
1005255Ssaidi@eecs.umich.edu
1014403Srdreslin@umich.edu    BaseMasterPort& getMasterPort() const;
1023358Srdreslin@umich.edu
1033358Srdreslin@umich.edu};
1044403Srdreslin@umich.edu
1055255Ssaidi@eecs.umich.edu/** Forward declaration */
1064403Srdreslin@umich.educlass SlavePort;
1073358Srdreslin@umich.edu
1083358Srdreslin@umich.edu/**
1094403Srdreslin@umich.edu * A MasterPort is a specialisation of a BaseMasterPort, which
1105255Ssaidi@eecs.umich.edu * implements the default protocol for the three different level of
1114403Srdreslin@umich.edu * transport functions. In addition to the basic functionality of
1124403Srdreslin@umich.edu * sending packets, it also has functions to receive range changes or
1133358Srdreslin@umich.edu * determine if the port is snooping or not.
1143358Srdreslin@umich.edu */
1154403Srdreslin@umich.educlass MasterPort : public BaseMasterPort
1165255Ssaidi@eecs.umich.edu{
1174403Srdreslin@umich.edu
1184403Srdreslin@umich.edu    friend class SlavePort;
1194403Srdreslin@umich.edu
1203360Srdreslin@umich.edu  private:
1214403Srdreslin@umich.edu
1223358Srdreslin@umich.edu    SlavePort* _slavePort;
1233358Srdreslin@umich.edu
1244403Srdreslin@umich.edu  protected:
1255255Ssaidi@eecs.umich.edu
1264403Srdreslin@umich.edu    SimObject& owner;
1273358Srdreslin@umich.edu
1283358Srdreslin@umich.edu  public:
1294403Srdreslin@umich.edu
1305255Ssaidi@eecs.umich.edu    MasterPort(const std::string& name, SimObject* _owner,
1314403Srdreslin@umich.edu               PortID id=InvalidPortID);
1323358Srdreslin@umich.edu    virtual ~MasterPort();
1333358Srdreslin@umich.edu
1344403Srdreslin@umich.edu    /**
1355256Ssaidi@eecs.umich.edu     * Bind this master port to a slave port. This also does the
1365255Ssaidi@eecs.umich.edu     * mirror action and binds the slave port to the master port.
1374403Srdreslin@umich.edu     */
1383358Srdreslin@umich.edu    void bind(Port &peer) override;
1393358Srdreslin@umich.edu
1404403Srdreslin@umich.edu    /**
1415255Ssaidi@eecs.umich.edu     * Unbind this master port and the associated slave port.
1424403Srdreslin@umich.edu     */
1434403Srdreslin@umich.edu    void unbind() override;
1444403Srdreslin@umich.edu
1453360Srdreslin@umich.edu    /**
1464403Srdreslin@umich.edu     * Send an atomic request packet, where the data is moved and the
1473358Srdreslin@umich.edu     * state is updated in zero time, without interleaving with other
1483358Srdreslin@umich.edu     * memory accesses.
1494403Srdreslin@umich.edu     *
1505255Ssaidi@eecs.umich.edu     * @param pkt Packet to send.
1514403Srdreslin@umich.edu     *
1524403Srdreslin@umich.edu     * @return Estimated latency of access.
1534403Srdreslin@umich.edu     */
1543360Srdreslin@umich.edu    Tick sendAtomic(PacketPtr pkt);
1554403Srdreslin@umich.edu
1563358Srdreslin@umich.edu    /**
1573358Srdreslin@umich.edu     * Send an atomic request packet like above, but also request a backdoor
1583358Srdreslin@umich.edu     * to the data being accessed.
1593358Srdreslin@umich.edu     *
1603358Srdreslin@umich.edu     * @param pkt Packet to send.
1613358Srdreslin@umich.edu     * @param backdoor Can be set to a back door pointer by the target to let
1623358Srdreslin@umich.edu     *        caller have direct access to the requested data.
1633358Srdreslin@umich.edu     *
1643358Srdreslin@umich.edu     * @return Estimated latency of access.
1653358Srdreslin@umich.edu     */
1663358Srdreslin@umich.edu    Tick sendAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor);
1673358Srdreslin@umich.edu
1683358Srdreslin@umich.edu    /**
1693358Srdreslin@umich.edu     * Send a functional request packet, where the data is instantly
1703358Srdreslin@umich.edu     * updated everywhere in the memory system, without affecting the
1713358Srdreslin@umich.edu     * current state of any block or moving the block.
1723358Srdreslin@umich.edu     *
1733358Srdreslin@umich.edu     * @param pkt Packet to send.
1743358Srdreslin@umich.edu     */
1753358Srdreslin@umich.edu    void sendFunctional(PacketPtr pkt);
1763358Srdreslin@umich.edu
1773358Srdreslin@umich.edu    /**
1783358Srdreslin@umich.edu     * Attempt to send a timing request to the slave port by calling
1793358Srdreslin@umich.edu     * its corresponding receive function. If the send does not
1803358Srdreslin@umich.edu     * succeed, as indicated by the return value, then the sender must
1813358Srdreslin@umich.edu     * wait for a recvReqRetry at which point it can re-issue a
1823358Srdreslin@umich.edu     * sendTimingReq.
1833358Srdreslin@umich.edu     *
1843358Srdreslin@umich.edu     * @param pkt Packet to send.
1853358Srdreslin@umich.edu     *
1863358Srdreslin@umich.edu     * @return If the send was succesful or not.
1873358Srdreslin@umich.edu    */
1883358Srdreslin@umich.edu    bool sendTimingReq(PacketPtr pkt);
1893358Srdreslin@umich.edu
1901516SN/A    /**
1913358Srdreslin@umich.edu     * Check if the slave can handle a timing request.
1923358Srdreslin@umich.edu     *
1933358Srdreslin@umich.edu     * If the send cannot be handled at the moment, as indicated by
1941516SN/A     * the return value, then the sender will receive a recvReqRetry
1953358Srdreslin@umich.edu     * at which point it can re-issue a sendTimingReq.
1963358Srdreslin@umich.edu     *
1973358Srdreslin@umich.edu     * @param pkt Packet to send.
1988931Sandreas.hansson@arm.com     *
19910720Sandreas.hansson@arm.com     * @return If the send was succesful or not.
2009790Sakash.bagdia@arm.com     */
2011516SN/A    bool tryTiming(PacketPtr pkt) const;
20210720Sandreas.hansson@arm.com
2033358Srdreslin@umich.edu    /**
2043358Srdreslin@umich.edu     * Attempt to send a timing snoop response packet to the slave
2053358Srdreslin@umich.edu     * port by calling its corresponding receive function. If the send
2063358Srdreslin@umich.edu     * does not succeed, as indicated by the return value, then the
2073358Srdreslin@umich.edu     * sender must wait for a recvRetrySnoop at which point it can
2083358Srdreslin@umich.edu     * re-issue a sendTimingSnoopResp.
2098847Sandreas.hansson@arm.com     *
2108847Sandreas.hansson@arm.com     * @param pkt Packet to send.
2118847Sandreas.hansson@arm.com     */
2128847Sandreas.hansson@arm.com    bool sendTimingSnoopResp(PacketPtr pkt);
2133358Srdreslin@umich.edu
2143358Srdreslin@umich.edu    /**
2153358Srdreslin@umich.edu     * Send a retry to the slave port that previously attempted a
2163358Srdreslin@umich.edu     * sendTimingResp to this master port and failed. Note that this
2173358Srdreslin@umich.edu     * is virtual so that the "fake" snoop response port in the
2183358Srdreslin@umich.edu     * coherent crossbar can override the behaviour.
2193358Srdreslin@umich.edu     */
2203358Srdreslin@umich.edu    virtual void sendRetryResp();
2217876Sgblack@eecs.umich.edu
2223358Srdreslin@umich.edu    /**
2233358Srdreslin@umich.edu     * Determine if this master port is snooping or not. The default
2243358Srdreslin@umich.edu     * implementation returns false and thus tells the neighbour we
2253358Srdreslin@umich.edu     * are not snooping. Any master port that wants to receive snoop
2263358Srdreslin@umich.edu     * requests (e.g. a cache connected to a bus) has to override this
2273358Srdreslin@umich.edu     * function.
2288801Sgblack@eecs.umich.edu     *
2293358Srdreslin@umich.edu     * @return true if the port should be considered a snooper
2303358Srdreslin@umich.edu     */
2313358Srdreslin@umich.edu    virtual bool isSnooping() const { return false; }
2323358Srdreslin@umich.edu
2333358Srdreslin@umich.edu    /**
2343358Srdreslin@umich.edu     * Get the address ranges of the connected slave port.
2353358Srdreslin@umich.edu     */
2363358Srdreslin@umich.edu    AddrRangeList getAddrRanges() const;
2373358Srdreslin@umich.edu
2383358Srdreslin@umich.edu    /** Inject a PrintReq for the given address to print the state of
2393358Srdreslin@umich.edu     * that address throughout the memory system.  For debugging.
2403358Srdreslin@umich.edu     */
2413358Srdreslin@umich.edu    void printAddr(Addr a);
2423358Srdreslin@umich.edu
2433358Srdreslin@umich.edu  protected:
2443358Srdreslin@umich.edu
2453358Srdreslin@umich.edu    /**
2463358Srdreslin@umich.edu     * Receive an atomic snoop request packet from the slave port.
2473358Srdreslin@umich.edu     */
2483358Srdreslin@umich.edu    virtual Tick recvAtomicSnoop(PacketPtr pkt)
2493358Srdreslin@umich.edu    {
2503358Srdreslin@umich.edu        panic("%s was not expecting an atomic snoop request\n", name());
2513358Srdreslin@umich.edu        return 0;
2523358Srdreslin@umich.edu    }
2533358Srdreslin@umich.edu
2543358Srdreslin@umich.edu    /**
2553358Srdreslin@umich.edu     * Receive a functional snoop request packet from the slave port.
2563358Srdreslin@umich.edu     */
2571516SN/A    virtual void recvFunctionalSnoop(PacketPtr pkt)
2585256Ssaidi@eecs.umich.edu    {
2595256Ssaidi@eecs.umich.edu        panic("%s was not expecting a functional snoop request\n", name());
2605256Ssaidi@eecs.umich.edu    }
2615256Ssaidi@eecs.umich.edu
2623358Srdreslin@umich.edu    /**
2633358Srdreslin@umich.edu     * Receive a timing response from the slave port.
2643358Srdreslin@umich.edu     */
2653358Srdreslin@umich.edu    virtual bool recvTimingResp(PacketPtr pkt) = 0;
2663358Srdreslin@umich.edu
2673358Srdreslin@umich.edu    /**
2683358Srdreslin@umich.edu     * Receive a timing snoop request from the slave port.
2693358Srdreslin@umich.edu     */
2703358Srdreslin@umich.edu    virtual void recvTimingSnoopReq(PacketPtr pkt)
2713358Srdreslin@umich.edu    {
2723358Srdreslin@umich.edu        panic("%s was not expecting a timing snoop request\n", name());
2733358Srdreslin@umich.edu    }
2743358Srdreslin@umich.edu
2753358Srdreslin@umich.edu    /**
2763358Srdreslin@umich.edu     * Called by the slave port if sendTimingReq was called on this
2773358Srdreslin@umich.edu     * master port (causing recvTimingReq to be called on the slave
2787525Ssteve.reinhardt@amd.com     * port) and was unsuccesful.
2793358Srdreslin@umich.edu     */
2803358Srdreslin@umich.edu    virtual void recvReqRetry() = 0;
2813358Srdreslin@umich.edu
2823358Srdreslin@umich.edu    /**
2833358Srdreslin@umich.edu     * Called by the slave port if sendTimingSnoopResp was called on this
2843646Srdreslin@umich.edu     * master port (causing recvTimingSnoopResp to be called on the slave
2853358Srdreslin@umich.edu     * port) and was unsuccesful.
2863358Srdreslin@umich.edu     */
2873358Srdreslin@umich.edu    virtual void recvRetrySnoopResp()
288    {
289        panic("%s was not expecting a snoop retry\n", name());
290    }
291
292    /**
293     * Called to receive an address range change from the peer slave
294     * port. The default implementation ignores the change and does
295     * nothing. Override this function in a derived class if the owner
296     * needs to be aware of the address ranges, e.g. in an
297     * interconnect component like a bus.
298     */
299    virtual void recvRangeChange() { }
300};
301
302/**
303 * A SlavePort is a specialisation of a port. In addition to the
304 * basic functionality of sending packets to its master peer, it also
305 * has functions specific to a slave, e.g. to send range changes
306 * and get the address ranges that the port responds to.
307 */
308class SlavePort : public BaseSlavePort
309{
310
311    friend class MasterPort;
312
313  private:
314
315    MasterPort* _masterPort;
316    bool defaultBackdoorWarned;
317
318  protected:
319
320    SimObject& owner;
321
322  public:
323
324    SlavePort(const std::string& name, SimObject* _owner,
325              PortID id=InvalidPortID);
326    virtual ~SlavePort();
327
328    /**
329     * Send an atomic snoop request packet, where the data is moved
330     * and the state is updated in zero time, without interleaving
331     * with other memory accesses.
332     *
333     * @param pkt Snoop packet to send.
334     *
335     * @return Estimated latency of access.
336     */
337    Tick sendAtomicSnoop(PacketPtr pkt);
338
339    /**
340     * Send a functional snoop request packet, where the data is
341     * instantly updated everywhere in the memory system, without
342     * affecting the current state of any block or moving the block.
343     *
344     * @param pkt Snoop packet to send.
345     */
346    void sendFunctionalSnoop(PacketPtr pkt);
347
348    /**
349     * Attempt to send a timing response to the master port by calling
350     * its corresponding receive function. If the send does not
351     * succeed, as indicated by the return value, then the sender must
352     * wait for a recvRespRetry at which point it can re-issue a
353     * sendTimingResp.
354     *
355     * @param pkt Packet to send.
356     *
357     * @return If the send was succesful or not.
358    */
359    bool sendTimingResp(PacketPtr pkt);
360
361    /**
362     * Attempt to send a timing snoop request packet to the master port
363     * by calling its corresponding receive function. Snoop requests
364     * always succeed and hence no return value is needed.
365     *
366     * @param pkt Packet to send.
367     */
368    void sendTimingSnoopReq(PacketPtr pkt);
369
370    /**
371     * Send a retry to the master port that previously attempted a
372     * sendTimingReq to this slave port and failed.
373     */
374    void sendRetryReq();
375
376    /**
377     * Send a retry to the master port that previously attempted a
378     * sendTimingSnoopResp to this slave port and failed.
379     */
380    void sendRetrySnoopResp();
381
382    /**
383     * Find out if the peer master port is snooping or not.
384     *
385     * @return true if the peer master port is snooping
386     */
387    bool isSnooping() const { return _masterPort->isSnooping(); }
388
389    /**
390     * Called by the owner to send a range change
391     */
392    void sendRangeChange() const {
393        if (!_masterPort)
394            fatal("%s cannot sendRangeChange() without master port", name());
395        _masterPort->recvRangeChange();
396    }
397
398    /**
399     * Get a list of the non-overlapping address ranges the owner is
400     * responsible for. All slave ports must override this function
401     * and return a populated list with at least one item.
402     *
403     * @return a list of ranges responded to
404     */
405    virtual AddrRangeList getAddrRanges() const = 0;
406
407    /**
408     * We let the master port do the work, so these don't do anything.
409     */
410    void unbind() override {}
411    void bind(Port &peer) override {}
412
413  protected:
414
415    /**
416     * Called by the master port to unbind. Should never be called
417     * directly.
418     */
419    void slaveUnbind();
420
421    /**
422     * Called by the master port to bind. Should never be called
423     * directly.
424     */
425    void slaveBind(MasterPort& master_port);
426
427    /**
428     * Receive an atomic request packet from the master port.
429     */
430    virtual Tick recvAtomic(PacketPtr pkt) = 0;
431
432    /**
433     * Receive an atomic request packet from the master port, and optionally
434     * provide a backdoor to the data being accessed.
435     */
436    virtual Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor);
437
438    /**
439     * Receive a functional request packet from the master port.
440     */
441    virtual void recvFunctional(PacketPtr pkt) = 0;
442
443    /**
444     * Receive a timing request from the master port.
445     */
446    virtual bool recvTimingReq(PacketPtr pkt) = 0;
447
448    /**
449     * Availability request from the master port.
450     */
451    virtual bool tryTiming(PacketPtr pkt) {
452        panic("%s was not expecting a %s\n", name(), __func__);
453    }
454
455    /**
456     * Receive a timing snoop response from the master port.
457     */
458    virtual bool recvTimingSnoopResp(PacketPtr pkt)
459    {
460        panic("%s was not expecting a timing snoop response\n", name());
461    }
462
463    /**
464     * Called by the master port if sendTimingResp was called on this
465     * slave port (causing recvTimingResp to be called on the master
466     * port) and was unsuccesful.
467     */
468    virtual void recvRespRetry() = 0;
469
470};
471
472#endif //__MEM_PORT_HH__
473