port.hh revision 5605
12381SN/A/*
22381SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
32381SN/A * All rights reserved.
42381SN/A *
52381SN/A * Redistribution and use in source and binary forms, with or without
62381SN/A * modification, are permitted provided that the following conditions are
72381SN/A * met: redistributions of source code must retain the above copyright
82381SN/A * notice, this list of conditions and the following disclaimer;
92381SN/A * redistributions in binary form must reproduce the above copyright
102381SN/A * notice, this list of conditions and the following disclaimer in the
112381SN/A * documentation and/or other materials provided with the distribution;
122381SN/A * neither the name of the copyright holders nor the names of its
132381SN/A * contributors may be used to endorse or promote products derived from
142381SN/A * this software without specific prior written permission.
152381SN/A *
162381SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172381SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182381SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192381SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202381SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212381SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222381SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232381SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242381SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252381SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262381SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski
292381SN/A */
302381SN/A
312381SN/A/**
322381SN/A * @file
332982Sstever@eecs.umich.edu * Port Object Declaration. Ports are used to interface memory objects to
342381SN/A * each other.  They will always come in pairs, and we refer to the other
352381SN/A * port object as the peer.  These are used to make the design more
362381SN/A * modular so that a specific interface between every type of objcet doesn't
372381SN/A * have to be created.
382381SN/A */
392381SN/A
402381SN/A#ifndef __MEM_PORT_HH__
412381SN/A#define __MEM_PORT_HH__
422381SN/A
432381SN/A#include <list>
442381SN/A#include <inttypes.h>
452381SN/A
462439SN/A#include "base/misc.hh"
472381SN/A#include "base/range.hh"
482381SN/A#include "mem/packet.hh"
492381SN/A#include "mem/request.hh"
505605Snate@binkert.org#include "sim/eventq.hh"
512381SN/A
522407SN/A/** This typedef is used to clean up the parameter list of
532407SN/A * getDeviceAddressRanges() and getPeerAddressRanges().  It's declared
542407SN/A * outside the Port object since it's also used by some mem objects.
552407SN/A * Eventually we should move this typedef to wherever Addr is
562407SN/A * defined.
572407SN/A */
582407SN/A
592407SN/Atypedef std::list<Range<Addr> > AddrRangeList;
602521SN/Atypedef std::list<Range<Addr> >::iterator AddrRangeIter;
612407SN/A
625605Snate@binkert.orgclass EventQueue;
633401Sktlim@umich.educlass MemObject;
643401Sktlim@umich.edu
652381SN/A/**
662381SN/A * Ports are used to interface memory objects to
672381SN/A * each other.  They will always come in pairs, and we refer to the other
682381SN/A * port object as the peer.  These are used to make the design more
692381SN/A * modular so that a specific interface between every type of objcet doesn't
702381SN/A * have to be created.
712381SN/A *
722381SN/A * Recv accesor functions are being called from the peer interface.
732381SN/A * Send accessor functions are being called from the device the port is
742381SN/A * associated with, and it will call the peer recv. accessor function.
752381SN/A */
765605Snate@binkert.orgclass Port : public EventManager
772381SN/A{
785476Snate@binkert.org  protected:
792640Sstever@eecs.umich.edu    /** Descriptive name (for DPRINTF output) */
802796Sktlim@umich.edu    mutable std::string portName;
812640Sstever@eecs.umich.edu
822661Sstever@eecs.umich.edu    /** A pointer to the peer port.  Ports always come in pairs, that way they
832661Sstever@eecs.umich.edu        can use a standardized interface to communicate between different
842661Sstever@eecs.umich.edu        memory objects. */
852661Sstever@eecs.umich.edu    Port *peer;
862661Sstever@eecs.umich.edu
873401Sktlim@umich.edu    /** A pointer to the MemObject that owns this port. This may not be set. */
883401Sktlim@umich.edu    MemObject *owner;
893401Sktlim@umich.edu
902381SN/A  public:
912640Sstever@eecs.umich.edu    /**
922640Sstever@eecs.umich.edu     * Constructor.
932640Sstever@eecs.umich.edu     *
942640Sstever@eecs.umich.edu     * @param _name Port name for DPRINTF output.  Should include name
952640Sstever@eecs.umich.edu     * of memory system object to which the port belongs.
963401Sktlim@umich.edu     * @param _owner Pointer to the MemObject that owns this port.
975494Sstever@gmail.com     * Will not necessarily be set.
982640Sstever@eecs.umich.edu     */
995605Snate@binkert.org    Port(const std::string &_name, MemObject *_owner);
1002640Sstever@eecs.umich.edu
1012640Sstever@eecs.umich.edu    /** Return port name (for DPRINTF). */
1022640Sstever@eecs.umich.edu    const std::string &name() const { return portName; }
1032640Sstever@eecs.umich.edu
1045476Snate@binkert.org    virtual ~Port();
1052640Sstever@eecs.umich.edu
1062381SN/A    // mey be better to use subclasses & RTTI?
1072657Ssaidi@eecs.umich.edu    /** Holds the ports status.  Currently just that a range recomputation needs
1082657Ssaidi@eecs.umich.edu     * to be done. */
1092381SN/A    enum Status {
1103173Srdreslin@umich.edu        RangeChange
1112381SN/A    };
1122381SN/A
1135494Sstever@gmail.com    void setName(const std::string &name)
1145494Sstever@gmail.com    { portName = name; }
1155494Sstever@gmail.com
1163401Sktlim@umich.edu    /** Function to set the pointer for the peer port. */
1174192Sktlim@umich.edu    virtual void setPeer(Port *port);
1182381SN/A
1193401Sktlim@umich.edu    /** Function to get the pointer to the peer port. */
1202409SN/A    Port *getPeer() { return peer; }
1212408SN/A
1225494Sstever@gmail.com    /** Function to set the owner of this port. */
1235605Snate@binkert.org    void setOwner(MemObject *_owner);
1245494Sstever@gmail.com
1253401Sktlim@umich.edu    /** Function to return the owner of this port. */
1263401Sktlim@umich.edu    MemObject *getOwner() { return owner; }
1273401Sktlim@umich.edu
1285494Sstever@gmail.com    /** Inform the peer port to delete itself and notify it's owner about it's
1295494Sstever@gmail.com     * demise. */
1305494Sstever@gmail.com    void removeConn();
1314190Ssaidi@eecs.umich.edu
1325476Snate@binkert.org    virtual bool isDefaultPort() const { return false; }
1335476Snate@binkert.org
1345476Snate@binkert.org    bool isConnected() { return peer && !peer->isDefaultPort(); }
1354190Ssaidi@eecs.umich.edu
1362381SN/A  protected:
1372381SN/A
1382406SN/A    /** These functions are protected because they should only be
1392406SN/A     * called by a peer port, never directly by any outside object. */
1402406SN/A
1412381SN/A    /** Called to recive a timing call from the peer port. */
1423349Sbinkertn@umich.edu    virtual bool recvTiming(PacketPtr pkt) = 0;
1432381SN/A
1442381SN/A    /** Called to recive a atomic call from the peer port. */
1453349Sbinkertn@umich.edu    virtual Tick recvAtomic(PacketPtr pkt) = 0;
1462381SN/A
1472381SN/A    /** Called to recive a functional call from the peer port. */
1483349Sbinkertn@umich.edu    virtual void recvFunctional(PacketPtr pkt) = 0;
1492381SN/A
1502381SN/A    /** Called to recieve a status change from the peer port. */
1512381SN/A    virtual void recvStatusChange(Status status) = 0;
1522381SN/A
1532381SN/A    /** Called by a peer port if the send was unsuccesful, and had to
1542381SN/A        wait.  This shouldn't be valid for response paths (IO Devices).
1552381SN/A        so it is set to panic if it isn't already defined.
1562381SN/A    */
1572657Ssaidi@eecs.umich.edu    virtual void recvRetry() { panic("??"); }
1582381SN/A
1592381SN/A    /** Called by a peer port in order to determine the block size of the
1602381SN/A        device connected to this port.  It sometimes doesn't make sense for
1614432Ssaidi@eecs.umich.edu        this function to be called, so it just returns 0. Anytthing that is
1624432Ssaidi@eecs.umich.edu        concerned with the size should just ignore that.
1632381SN/A    */
1644432Ssaidi@eecs.umich.edu    virtual int deviceBlockSize() { return 0; }
1652381SN/A
1662381SN/A    /** The peer port is requesting us to reply with a list of the ranges we
1672381SN/A        are responsible for.
1682521SN/A        @param resp is a list of ranges responded to
1692521SN/A        @param snoop is a list of ranges snooped
1702381SN/A    */
1712521SN/A    virtual void getDeviceAddressRanges(AddrRangeList &resp,
1724475Sstever@eecs.umich.edu                                        bool &snoop)
1732407SN/A    { panic("??"); }
1742381SN/A
1752381SN/A  public:
1762381SN/A
1772381SN/A    /** Function called by associated memory device (cache, memory, iodevice)
1782381SN/A        in order to send a timing request to the port.  Simply calls the peer
1792381SN/A        port receive function.
1802381SN/A        @return This function returns if the send was succesful in it's
1812381SN/A        recieve. If it was a failure, then the port will wait for a recvRetry
1822657Ssaidi@eecs.umich.edu        at which point it can possibly issue a successful sendTiming.  This is used in
1832381SN/A        case a cache has a higher priority request come in while waiting for
1842381SN/A        the bus to arbitrate.
1852381SN/A    */
1863349Sbinkertn@umich.edu    bool sendTiming(PacketPtr pkt) { return peer->recvTiming(pkt); }
1872381SN/A
1882662Sstever@eecs.umich.edu    /** Function called by the associated device to send an atomic
1892662Sstever@eecs.umich.edu     *   access, an access in which the data is moved and the state is
1902662Sstever@eecs.umich.edu     *   updated in one cycle, without interleaving with other memory
1912662Sstever@eecs.umich.edu     *   accesses.  Returns estimated latency of access.
1922662Sstever@eecs.umich.edu     */
1933349Sbinkertn@umich.edu    Tick sendAtomic(PacketPtr pkt)
1942381SN/A        { return peer->recvAtomic(pkt); }
1952381SN/A
1962381SN/A    /** Function called by the associated device to send a functional access,
1972381SN/A        an access in which the data is instantly updated everywhere in the
1982520SN/A        memory system, without affecting the current state of any block or
1992520SN/A        moving the block.
2002381SN/A    */
2013349Sbinkertn@umich.edu    void sendFunctional(PacketPtr pkt)
2022381SN/A        { return peer->recvFunctional(pkt); }
2032381SN/A
2042381SN/A    /** Called by the associated device to send a status change to the device
2052381SN/A        connected to the peer interface.
2062381SN/A    */
2072381SN/A    void sendStatusChange(Status status) {peer->recvStatusChange(status); }
2082381SN/A
2092381SN/A    /** When a timing access doesn't return a success, some time later the
2102381SN/A        Retry will be sent.
2112381SN/A    */
2122657Ssaidi@eecs.umich.edu    void sendRetry() { return peer->recvRetry(); }
2132381SN/A
2142381SN/A    /** Called by the associated device if it wishes to find out the blocksize
2152381SN/A        of the device on attached to the peer port.
2162381SN/A    */
2172406SN/A    int peerBlockSize() { return peer->deviceBlockSize(); }
2182381SN/A
2192381SN/A    /** Called by the associated device if it wishes to find out the address
2202381SN/A        ranges connected to the peer ports devices.
2212381SN/A    */
2224475Sstever@eecs.umich.edu    void getPeerAddressRanges(AddrRangeList &resp, bool &snoop)
2232521SN/A    { peer->getDeviceAddressRanges(resp, snoop); }
2242381SN/A
2252461SN/A    /** This function is a wrapper around sendFunctional()
2262461SN/A        that breaks a larger, arbitrarily aligned access into
2272461SN/A        appropriate chunks.  The default implementation can use
2282461SN/A        getBlockSize() to determine the block size and go from there.
2292461SN/A    */
2302519SN/A    virtual void readBlob(Addr addr, uint8_t *p, int size);
2312381SN/A
2322381SN/A    /** This function is a wrapper around sendFunctional()
2332381SN/A        that breaks a larger, arbitrarily aligned access into
2342381SN/A        appropriate chunks.  The default implementation can use
2352381SN/A        getBlockSize() to determine the block size and go from there.
2362381SN/A    */
2372519SN/A    virtual void writeBlob(Addr addr, uint8_t *p, int size);
2382381SN/A
2392381SN/A    /** Fill size bytes starting at addr with byte value val.  This
2402381SN/A        should not need to be virtual, since it can be implemented in
2412461SN/A        terms of writeBlob().  However, it shouldn't be
2422381SN/A        performance-critical either, so it could be if we wanted to.
2432381SN/A    */
2442519SN/A    virtual void memsetBlob(Addr addr, uint8_t val, int size);
2452405SN/A
2465314Sstever@gmail.com    /** Inject a PrintReq for the given address to print the state of
2475314Sstever@gmail.com     * that address throughout the memory system.  For debugging.
2485314Sstever@gmail.com     */
2495314Sstever@gmail.com    void printAddr(Addr a);
2505314Sstever@gmail.com
2512405SN/A  private:
2522405SN/A
2532405SN/A    /** Internal helper function for read/writeBlob().
2542405SN/A     */
2554022Sstever@eecs.umich.edu    void blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd);
2562381SN/A};
2572381SN/A
2582520SN/A/** A simple functional port that is only meant for one way communication to
2592520SN/A * physical memory. It is only meant to be used to load data into memory before
2602520SN/A * the simulation begins.
2612520SN/A */
2622520SN/A
2632520SN/Aclass FunctionalPort : public Port
2642520SN/A{
2652520SN/A  public:
2663401Sktlim@umich.edu    FunctionalPort(const std::string &_name, MemObject *_owner = NULL)
2673401Sktlim@umich.edu        : Port(_name, _owner)
2682640Sstever@eecs.umich.edu    {}
2692640Sstever@eecs.umich.edu
2703091Sstever@eecs.umich.edu  protected:
2713918Ssaidi@eecs.umich.edu    virtual bool recvTiming(PacketPtr pkt) { panic("FuncPort is UniDir");
2723918Ssaidi@eecs.umich.edu        M5_DUMMY_RETURN }
2733918Ssaidi@eecs.umich.edu    virtual Tick recvAtomic(PacketPtr pkt) { panic("FuncPort is UniDir");
2743918Ssaidi@eecs.umich.edu        M5_DUMMY_RETURN }
2753349Sbinkertn@umich.edu    virtual void recvFunctional(PacketPtr pkt) { panic("FuncPort is UniDir"); }
2762590SN/A    virtual void recvStatusChange(Status status) {}
2772521SN/A
2783091Sstever@eecs.umich.edu  public:
2792684Ssaidi@eecs.umich.edu    /** a write function that also does an endian conversion. */
2802684Ssaidi@eecs.umich.edu    template <typename T>
2812684Ssaidi@eecs.umich.edu    inline void writeHtoG(Addr addr, T d);
2822684Ssaidi@eecs.umich.edu
2832684Ssaidi@eecs.umich.edu    /** a read function that also does an endian conversion. */
2842684Ssaidi@eecs.umich.edu    template <typename T>
2852684Ssaidi@eecs.umich.edu    inline T readGtoH(Addr addr);
2862684Ssaidi@eecs.umich.edu
2872521SN/A    template <typename T>
2882521SN/A    inline void write(Addr addr, T d)
2892521SN/A    {
2902521SN/A        writeBlob(addr, (uint8_t*)&d, sizeof(T));
2912521SN/A    }
2922521SN/A
2932521SN/A    template <typename T>
2942521SN/A    inline T read(Addr addr)
2952521SN/A    {
2962521SN/A        T d;
2972521SN/A        readBlob(addr, (uint8_t*)&d, sizeof(T));
2982521SN/A        return d;
2992521SN/A    }
3002520SN/A};
3012520SN/A
3022381SN/A#endif //__MEM_PORT_HH__
303