port.hh revision 9088
13358Srdreslin@umich.edu/*
21693Sstever@eecs.umich.edu * Copyright (c) 2011-2012 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
323358Srdreslin@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
333358Srdreslin@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
343358Srdreslin@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
353358Srdreslin@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
361516SN/A * 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
383358Srdreslin@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
393358Srdreslin@umich.edu *
403358Srdreslin@umich.edu * 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 */
493360Srdreslin@umich.edu
503358Srdreslin@umich.edu#ifndef __MEM_PORT_HH__
513358Srdreslin@umich.edu#define __MEM_PORT_HH__
523358Srdreslin@umich.edu
533358Srdreslin@umich.edu#include <list>
543360Srdreslin@umich.edu
553360Srdreslin@umich.edu#include "base/range.hh"
563360Srdreslin@umich.edu#include "mem/packet.hh"
573360Srdreslin@umich.edu
583360Srdreslin@umich.edu/**
593360Srdreslin@umich.edu * This typedef is used to clean up getAddrRanges(). It's declared
603360Srdreslin@umich.edu * outside the Port object since it's also used by some mem objects.
613360Srdreslin@umich.edu * Eventually we should move this typedef to wherever Addr is
623358Srdreslin@umich.edu * defined.
633358Srdreslin@umich.edu */
643360Srdreslin@umich.edu
653358Srdreslin@umich.edutypedef std::list<Range<Addr> > AddrRangeList;
663358Srdreslin@umich.edutypedef std::list<Range<Addr> >::iterator AddrRangeIter;
673358Srdreslin@umich.edu
683358Srdreslin@umich.educlass MemObject;
693358Srdreslin@umich.edu
703358Srdreslin@umich.edu/**
713358Srdreslin@umich.edu * Ports are used to interface memory objects to each other. A port is
723358Srdreslin@umich.edu * either a master or a slave and the connected peer is always of the
733358Srdreslin@umich.edu * opposite role. Each port has a name, an owner, and an identifier.
743360Srdreslin@umich.edu */
753360Srdreslin@umich.educlass Port
763360Srdreslin@umich.edu{
773360Srdreslin@umich.edu
783358Srdreslin@umich.edu  private:
793358Srdreslin@umich.edu
803358Srdreslin@umich.edu    /** Descriptive name (for DPRINTF output) */
813358Srdreslin@umich.edu    std::string portName;
823358Srdreslin@umich.edu
833358Srdreslin@umich.edu  protected:
843358Srdreslin@umich.edu
853358Srdreslin@umich.edu    /**
863358Srdreslin@umich.edu     * A numeric identifier to distinguish ports in a vector, and set
873360Srdreslin@umich.edu     * to InvalidPortID in case this port is not part of a vector.
883358Srdreslin@umich.edu     */
893358Srdreslin@umich.edu    const PortID id;
903358Srdreslin@umich.edu
913360Srdreslin@umich.edu    /** A reference to the MemObject that owns this port. */
923358Srdreslin@umich.edu    MemObject& owner;
933358Srdreslin@umich.edu
943358Srdreslin@umich.edu    /**
953360Srdreslin@umich.edu     * Abstract base class for ports
963358Srdreslin@umich.edu     *
973358Srdreslin@umich.edu     * @param _name Port name including the owners name
983358Srdreslin@umich.edu     * @param _owner The MemObject that is the structural owner of this port
993360Srdreslin@umich.edu     * @param _id A port identifier for vector ports
1003358Srdreslin@umich.edu     */
1013358Srdreslin@umich.edu    Port(const std::string& _name, MemObject& _owner, PortID _id);
1023358Srdreslin@umich.edu
1033360Srdreslin@umich.edu    /**
1043358Srdreslin@umich.edu     * Virtual destructor due to inheritance.
1053360Srdreslin@umich.edu     */
1063358Srdreslin@umich.edu    virtual ~Port();
1073358Srdreslin@umich.edu
1083360Srdreslin@umich.edu  public:
1093358Srdreslin@umich.edu
1103360Srdreslin@umich.edu    /** Return port name (for DPRINTF). */
1113358Srdreslin@umich.edu    const std::string name() const { return portName; }
1123358Srdreslin@umich.edu
1133360Srdreslin@umich.edu    /** Get the port id. */
1143358Srdreslin@umich.edu    PortID getId() const { return id; }
1153358Srdreslin@umich.edu
1163358Srdreslin@umich.edu};
1173360Srdreslin@umich.edu
1183358Srdreslin@umich.edu/** Forward declaration */
1193358Srdreslin@umich.educlass SlavePort;
1203358Srdreslin@umich.edu
1213360Srdreslin@umich.edu/**
1223358Srdreslin@umich.edu * A MasterPort is a specialisation of a port. In addition to the
1233358Srdreslin@umich.edu * basic functionality of sending packets to its slave peer, it also
1243358Srdreslin@umich.edu * has functions specific to a master, e.g. to receive range changes
1253358Srdreslin@umich.edu * or determine if the port is snooping or not.
1263360Srdreslin@umich.edu */
1273358Srdreslin@umich.educlass MasterPort : public Port
1283360Srdreslin@umich.edu{
1293358Srdreslin@umich.edu
1303358Srdreslin@umich.edu    friend class SlavePort;
1313360Srdreslin@umich.edu
1323358Srdreslin@umich.edu  private:
1333360Srdreslin@umich.edu
1343358Srdreslin@umich.edu    SlavePort* _slavePort;
1353358Srdreslin@umich.edu
1363358Srdreslin@umich.edu  public:
1373358Srdreslin@umich.edu
1383358Srdreslin@umich.edu    MasterPort(const std::string& name, MemObject* owner,
1393358Srdreslin@umich.edu               PortID id = InvalidPortID);
1403358Srdreslin@umich.edu    virtual ~MasterPort();
1413358Srdreslin@umich.edu
1423358Srdreslin@umich.edu    void bind(SlavePort& slave_port);
1433358Srdreslin@umich.edu    SlavePort& getSlavePort() const;
1443358Srdreslin@umich.edu    bool isConnected() const;
1453358Srdreslin@umich.edu
1463358Srdreslin@umich.edu    /**
1473358Srdreslin@umich.edu     * Send an atomic request packet, where the data is moved and the
1483358Srdreslin@umich.edu     * state is updated in zero time, without interleaving with other
1493358Srdreslin@umich.edu     * memory accesses.
1503358Srdreslin@umich.edu     *
1513358Srdreslin@umich.edu     * @param pkt Packet to send.
1523358Srdreslin@umich.edu     *
1533358Srdreslin@umich.edu     * @return Estimated latency of access.
1543358Srdreslin@umich.edu     */
1553358Srdreslin@umich.edu    Tick sendAtomic(PacketPtr pkt);
1563358Srdreslin@umich.edu
1573358Srdreslin@umich.edu    /**
1583358Srdreslin@umich.edu     * Send a functional request packet, where the data is instantly
1593358Srdreslin@umich.edu     * updated everywhere in the memory system, without affecting the
1603358Srdreslin@umich.edu     * current state of any block or moving the block.
1613358Srdreslin@umich.edu     *
1623358Srdreslin@umich.edu     * @param pkt Packet to send.
1633358Srdreslin@umich.edu     */
1643358Srdreslin@umich.edu    void sendFunctional(PacketPtr pkt);
1653358Srdreslin@umich.edu
1663358Srdreslin@umich.edu    /**
1673358Srdreslin@umich.edu     * Attempt to send a timing request to the slave port by calling
1683358Srdreslin@umich.edu     * its corresponding receive function. If the send does not
1693358Srdreslin@umich.edu     * succeed, as indicated by the return value, then the sender must
1703358Srdreslin@umich.edu     * wait for a recvRetry at which point it can re-issue a
1713358Srdreslin@umich.edu     * sendTimingReq.
1721516SN/A     *
1733358Srdreslin@umich.edu     * @param pkt Packet to send.
1743358Srdreslin@umich.edu     *
1753358Srdreslin@umich.edu     * @return If the send was succesful or not.
1761516SN/A    */
1773358Srdreslin@umich.edu    bool sendTimingReq(PacketPtr pkt);
1783358Srdreslin@umich.edu
1793358Srdreslin@umich.edu    /**
1803358Srdreslin@umich.edu     * Attempt to send a timing snoop response packet to the slave
1813358Srdreslin@umich.edu     * port by calling its corresponding receive function. If the send
1821516SN/A     * does not succeed, as indicated by the return value, then the
1833358Srdreslin@umich.edu     * sender must wait for a recvRetry at which point it can re-issue
1843358Srdreslin@umich.edu     * a sendTimingSnoopResp.
1853358Srdreslin@umich.edu     *
1863358Srdreslin@umich.edu     * @param pkt Packet to send.
1873358Srdreslin@umich.edu     */
1883358Srdreslin@umich.edu    bool sendTimingSnoopResp(PacketPtr pkt);
1893358Srdreslin@umich.edu
1903358Srdreslin@umich.edu    /**
1913358Srdreslin@umich.edu     * Send a retry to the slave port that previously attempted a
1923358Srdreslin@umich.edu     * sendTimingResp to this master port and failed.
1933358Srdreslin@umich.edu     */
1943358Srdreslin@umich.edu    void sendRetry();
1953358Srdreslin@umich.edu
1963358Srdreslin@umich.edu    /**
1973358Srdreslin@umich.edu     * Determine if this master port is snooping or not. The default
1983358Srdreslin@umich.edu     * implementation returns false and thus tells the neighbour we
1993358Srdreslin@umich.edu     * are not snooping. Any master port that wants to receive snoop
2003358Srdreslin@umich.edu     * requests (e.g. a cache connected to a bus) has to override this
2013358Srdreslin@umich.edu     * function.
2023358Srdreslin@umich.edu     *
2033358Srdreslin@umich.edu     * @return true if the port should be considered a snooper
2043358Srdreslin@umich.edu     */
2053358Srdreslin@umich.edu    virtual bool isSnooping() const { return false; }
2063358Srdreslin@umich.edu
2073358Srdreslin@umich.edu    /**
2083358Srdreslin@umich.edu     * Called by a peer port in order to determine the block size of
2093358Srdreslin@umich.edu     * the owner of this port.
2103358Srdreslin@umich.edu     */
2113358Srdreslin@umich.edu    virtual unsigned deviceBlockSize() const { return 0; }
2123358Srdreslin@umich.edu
2133358Srdreslin@umich.edu    /** Called by the associated device if it wishes to find out the blocksize
2143358Srdreslin@umich.edu        of the device on attached to the peer port.
2153358Srdreslin@umich.edu    */
2163358Srdreslin@umich.edu    unsigned peerBlockSize() const;
2173358Srdreslin@umich.edu
2183358Srdreslin@umich.edu    /** Inject a PrintReq for the given address to print the state of
2193358Srdreslin@umich.edu     * that address throughout the memory system.  For debugging.
2203358Srdreslin@umich.edu     */
2213358Srdreslin@umich.edu    void printAddr(Addr a);
2223358Srdreslin@umich.edu
2233358Srdreslin@umich.edu  protected:
2243358Srdreslin@umich.edu
2253358Srdreslin@umich.edu    /**
2263358Srdreslin@umich.edu     * Receive an atomic snoop request packet from the slave port.
2273358Srdreslin@umich.edu     */
2283358Srdreslin@umich.edu    virtual Tick recvAtomicSnoop(PacketPtr pkt)
2293358Srdreslin@umich.edu    {
2303358Srdreslin@umich.edu        panic("%s was not expecting an atomic snoop request\n", name());
2313358Srdreslin@umich.edu        return 0;
2323358Srdreslin@umich.edu    }
2333358Srdreslin@umich.edu
2343358Srdreslin@umich.edu    /**
2353358Srdreslin@umich.edu     * Receive a functional snoop request packet from the slave port.
2363358Srdreslin@umich.edu     */
2373358Srdreslin@umich.edu    virtual void recvFunctionalSnoop(PacketPtr pkt)
2381516SN/A    {
2393358Srdreslin@umich.edu        panic("%s was not expecting a functional snoop request\n", name());
2401516SN/A    }
2411516SN/A
2421516SN/A    /**
2433358Srdreslin@umich.edu     * Receive a timing response from the slave port.
2443358Srdreslin@umich.edu     */
2453358Srdreslin@umich.edu    virtual bool recvTimingResp(PacketPtr pkt) = 0;
2463358Srdreslin@umich.edu
2473358Srdreslin@umich.edu    /**
2483358Srdreslin@umich.edu     * Receive a timing snoop request from the slave port.
2493358Srdreslin@umich.edu     */
2503358Srdreslin@umich.edu    virtual void recvTimingSnoopReq(PacketPtr pkt)
2513358Srdreslin@umich.edu    {
2523358Srdreslin@umich.edu        panic("%s was not expecting a timing snoop request\n", name());
2533358Srdreslin@umich.edu    }
2543358Srdreslin@umich.edu
2553358Srdreslin@umich.edu    /**
2563358Srdreslin@umich.edu     * Called by the slave port if sendTimingReq or
2573358Srdreslin@umich.edu     * sendTimingSnoopResp was called on this master port (causing
2583358Srdreslin@umich.edu     * recvTimingReq and recvTimingSnoopResp to be called on the
2593358Srdreslin@umich.edu     * slave port) and was unsuccesful.
2603358Srdreslin@umich.edu     */
2613358Srdreslin@umich.edu    virtual void recvRetry() = 0;
2623358Srdreslin@umich.edu
2633358Srdreslin@umich.edu    /**
2643358Srdreslin@umich.edu     * Called to receive an address range change from the peer slave
2653358Srdreslin@umich.edu     * port. the default implementation ignored the change and does
2663358Srdreslin@umich.edu     * nothing. Override this function in a derived class if the owner
2673358Srdreslin@umich.edu     * needs to be aware of he laesddress ranges, e.g. in an
2683358Srdreslin@umich.edu     * interconnect component like a bus.
269     */
270    virtual void recvRangeChange() { }
271};
272
273/**
274 * A SlavePort is a specialisation of a port. In addition to the
275 * basic functionality of sending packets to its master peer, it also
276 * has functions specific to a slave, e.g. to send range changes
277 * and get the address ranges that the port responds to.
278 */
279class SlavePort : public Port
280{
281
282    friend class MasterPort;
283
284  private:
285
286    MasterPort* _masterPort;
287
288  public:
289
290    SlavePort(const std::string& name, MemObject* owner,
291              PortID id = InvalidPortID);
292    virtual ~SlavePort();
293
294    void bind(MasterPort& master_port);
295    MasterPort& getMasterPort() const;
296    bool isConnected() const;
297
298    /**
299     * Send an atomic snoop request packet, where the data is moved
300     * and the state is updated in zero time, without interleaving
301     * with other memory accesses.
302     *
303     * @param pkt Snoop packet to send.
304     *
305     * @return Estimated latency of access.
306     */
307    Tick sendAtomicSnoop(PacketPtr pkt);
308
309    /**
310     * Send a functional snoop request packet, where the data is
311     * instantly updated everywhere in the memory system, without
312     * affecting the current state of any block or moving the block.
313     *
314     * @param pkt Snoop packet to send.
315     */
316    void sendFunctionalSnoop(PacketPtr pkt);
317
318    /**
319     * Attempt to send a timing response to the master port by calling
320     * its corresponding receive function. If the send does not
321     * succeed, as indicated by the return value, then the sender must
322     * wait for a recvRetry at which point it can re-issue a
323     * sendTimingResp.
324     *
325     * @param pkt Packet to send.
326     *
327     * @return If the send was succesful or not.
328    */
329    bool sendTimingResp(PacketPtr pkt);
330
331    /**
332     * Attempt to send a timing snoop request packet to the master port
333     * by calling its corresponding receive function. Snoop requests
334     * always succeed and hence no return value is needed.
335     *
336     * @param pkt Packet to send.
337     */
338    void sendTimingSnoopReq(PacketPtr pkt);
339
340    /**
341     * Send a retry to the master port that previously attempted a
342     * sendTimingReq or sendTimingSnoopResp to this slave port and
343     * failed.
344     */
345    void sendRetry();
346
347    /**
348     * Called by a peer port in order to determine the block size of
349     * the owner of this port.
350     */
351    virtual unsigned deviceBlockSize() const { return 0; }
352
353    /** Called by the associated device if it wishes to find out the blocksize
354        of the device on attached to the peer port.
355    */
356    unsigned peerBlockSize() const;
357
358    /**
359     * Find out if the peer master port is snooping or not.
360     *
361     * @return true if the peer master port is snooping
362     */
363    bool isSnooping() const { return _masterPort->isSnooping(); }
364
365    /**
366     * Called by the owner to send a range change
367     */
368    void sendRangeChange() const { _masterPort->recvRangeChange(); }
369
370    /**
371     * Get a list of the non-overlapping address ranges the owner is
372     * responsible for. All slave ports must override this function
373     * and return a populated list with at least one item.
374     *
375     * @return a list of ranges responded to
376     */
377    virtual AddrRangeList getAddrRanges() = 0;
378
379  protected:
380
381    /**
382     * Receive an atomic request packet from the master port.
383     */
384    virtual Tick recvAtomic(PacketPtr pkt) = 0;
385
386    /**
387     * Receive a functional request packet from the master port.
388     */
389    virtual void recvFunctional(PacketPtr pkt) = 0;
390
391    /**
392     * Receive a timing request from the master port.
393     */
394    virtual bool recvTimingReq(PacketPtr pkt) = 0;
395
396    /**
397     * Receive a timing snoop response from the master port.
398     */
399    virtual bool recvTimingSnoopResp(PacketPtr pkt)
400    {
401        panic("%s was not expecting a timing snoop response\n", name());
402    }
403
404    /**
405     * Called by the master port if sendTimingResp was called on this
406     * slave port (causing recvTimingResp to be called on the master
407     * port) and was unsuccesful.
408     */
409    virtual void recvRetry() = 0;
410
411};
412
413#endif //__MEM_PORT_HH__
414