port.hh revision 2641:6d9d837e2032
112027Sjungma@eit.uni-kl.de/*
212027Sjungma@eit.uni-kl.de * Copyright (c) 2002-2005 The Regents of The University of Michigan
312027Sjungma@eit.uni-kl.de * All rights reserved.
412027Sjungma@eit.uni-kl.de *
512027Sjungma@eit.uni-kl.de * Redistribution and use in source and binary forms, with or without
612027Sjungma@eit.uni-kl.de * modification, are permitted provided that the following conditions are
712027Sjungma@eit.uni-kl.de * met: redistributions of source code must retain the above copyright
812027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer;
912027Sjungma@eit.uni-kl.de * redistributions in binary form must reproduce the above copyright
1012027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer in the
1112027Sjungma@eit.uni-kl.de * documentation and/or other materials provided with the distribution;
1212027Sjungma@eit.uni-kl.de * neither the name of the copyright holders nor the names of its
1312027Sjungma@eit.uni-kl.de * contributors may be used to endorse or promote products derived from
1412027Sjungma@eit.uni-kl.de * this software without specific prior written permission.
1512027Sjungma@eit.uni-kl.de *
1612027Sjungma@eit.uni-kl.de * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712027Sjungma@eit.uni-kl.de * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812027Sjungma@eit.uni-kl.de * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912027Sjungma@eit.uni-kl.de * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012027Sjungma@eit.uni-kl.de * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112027Sjungma@eit.uni-kl.de * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212027Sjungma@eit.uni-kl.de * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312027Sjungma@eit.uni-kl.de * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412027Sjungma@eit.uni-kl.de * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512027Sjungma@eit.uni-kl.de * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612027Sjungma@eit.uni-kl.de * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712027Sjungma@eit.uni-kl.de */
2812027Sjungma@eit.uni-kl.de
2912027Sjungma@eit.uni-kl.de/**
3012027Sjungma@eit.uni-kl.de * @file
3112027Sjungma@eit.uni-kl.de * Port Object Decleration. Ports are used to interface memory objects to
3212027Sjungma@eit.uni-kl.de * each other.  They will always come in pairs, and we refer to the other
3312027Sjungma@eit.uni-kl.de * port object as the peer.  These are used to make the design more
3412027Sjungma@eit.uni-kl.de * modular so that a specific interface between every type of objcet doesn't
3512027Sjungma@eit.uni-kl.de * have to be created.
3612027Sjungma@eit.uni-kl.de */
3712027Sjungma@eit.uni-kl.de
3812027Sjungma@eit.uni-kl.de#ifndef __MEM_PORT_HH__
3912027Sjungma@eit.uni-kl.de#define __MEM_PORT_HH__
4012027Sjungma@eit.uni-kl.de
4112027Sjungma@eit.uni-kl.de#include <list>
4212027Sjungma@eit.uni-kl.de#include <inttypes.h>
4312027Sjungma@eit.uni-kl.de
4412027Sjungma@eit.uni-kl.de#include "base/misc.hh"
4512027Sjungma@eit.uni-kl.de#include "base/range.hh"
4612027Sjungma@eit.uni-kl.de#include "mem/packet.hh"
4712027Sjungma@eit.uni-kl.de#include "mem/request.hh"
4812027Sjungma@eit.uni-kl.de
4912027Sjungma@eit.uni-kl.de/** This typedef is used to clean up the parameter list of
5012027Sjungma@eit.uni-kl.de * getDeviceAddressRanges() and getPeerAddressRanges().  It's declared
5112027Sjungma@eit.uni-kl.de * outside the Port object since it's also used by some mem objects.
5212027Sjungma@eit.uni-kl.de * Eventually we should move this typedef to wherever Addr is
5312027Sjungma@eit.uni-kl.de * defined.
5412027Sjungma@eit.uni-kl.de */
5512027Sjungma@eit.uni-kl.de
5612027Sjungma@eit.uni-kl.detypedef std::list<Range<Addr> > AddrRangeList;
5712027Sjungma@eit.uni-kl.detypedef std::list<Range<Addr> >::iterator AddrRangeIter;
5812027Sjungma@eit.uni-kl.de
5912027Sjungma@eit.uni-kl.de/**
6012027Sjungma@eit.uni-kl.de * Ports are used to interface memory objects to
6112027Sjungma@eit.uni-kl.de * each other.  They will always come in pairs, and we refer to the other
6212027Sjungma@eit.uni-kl.de * port object as the peer.  These are used to make the design more
6312027Sjungma@eit.uni-kl.de * modular so that a specific interface between every type of objcet doesn't
6412027Sjungma@eit.uni-kl.de * have to be created.
6512027Sjungma@eit.uni-kl.de *
6612027Sjungma@eit.uni-kl.de * Recv accesor functions are being called from the peer interface.
6712027Sjungma@eit.uni-kl.de * Send accessor functions are being called from the device the port is
6812027Sjungma@eit.uni-kl.de * associated with, and it will call the peer recv. accessor function.
6912027Sjungma@eit.uni-kl.de */
7012027Sjungma@eit.uni-kl.declass Port
7112027Sjungma@eit.uni-kl.de{
7212027Sjungma@eit.uni-kl.de  private:
7312027Sjungma@eit.uni-kl.de
7412027Sjungma@eit.uni-kl.de    /** Descriptive name (for DPRINTF output) */
7512027Sjungma@eit.uni-kl.de    const std::string portName;
7612027Sjungma@eit.uni-kl.de
7712027Sjungma@eit.uni-kl.de  public:
7812027Sjungma@eit.uni-kl.de
7912027Sjungma@eit.uni-kl.de    /**
8012027Sjungma@eit.uni-kl.de     * Constructor.
8112027Sjungma@eit.uni-kl.de     *
8212027Sjungma@eit.uni-kl.de     * @param _name Port name for DPRINTF output.  Should include name
8312027Sjungma@eit.uni-kl.de     * of memory system object to which the port belongs.
8412027Sjungma@eit.uni-kl.de     */
8512027Sjungma@eit.uni-kl.de    Port(const std::string &_name)
8612027Sjungma@eit.uni-kl.de        : portName(_name)
8712027Sjungma@eit.uni-kl.de    { }
8812027Sjungma@eit.uni-kl.de
8912027Sjungma@eit.uni-kl.de    /** Return port name (for DPRINTF). */
9012027Sjungma@eit.uni-kl.de    const std::string &name() const { return portName; }
9112027Sjungma@eit.uni-kl.de
9212027Sjungma@eit.uni-kl.de    virtual ~Port() {};
9312027Sjungma@eit.uni-kl.de
9412027Sjungma@eit.uni-kl.de    // mey be better to use subclasses & RTTI?
9512027Sjungma@eit.uni-kl.de    /** Holds the ports status.  Keeps track if it is blocked, or has
9612027Sjungma@eit.uni-kl.de        calculated a range change. */
9712027Sjungma@eit.uni-kl.de    enum Status {
9812027Sjungma@eit.uni-kl.de        Blocked,
9912027Sjungma@eit.uni-kl.de        Unblocked,
10012027Sjungma@eit.uni-kl.de        RangeChange
10112027Sjungma@eit.uni-kl.de    };
10212027Sjungma@eit.uni-kl.de
10312027Sjungma@eit.uni-kl.de  private:
10412027Sjungma@eit.uni-kl.de
10512027Sjungma@eit.uni-kl.de    /** A pointer to the peer port.  Ports always come in pairs, that way they
10612027Sjungma@eit.uni-kl.de        can use a standardized interface to communicate between different
10712027Sjungma@eit.uni-kl.de        memory objects. */
10812027Sjungma@eit.uni-kl.de    Port *peer;
10912027Sjungma@eit.uni-kl.de
11012027Sjungma@eit.uni-kl.de  public:
11112027Sjungma@eit.uni-kl.de
11212027Sjungma@eit.uni-kl.de    /** Function to set the pointer for the peer port.
11312027Sjungma@eit.uni-kl.de        @todo should be called by the configuration stuff (python).
11412027Sjungma@eit.uni-kl.de    */
11512027Sjungma@eit.uni-kl.de    void setPeer(Port *port) { peer = port; }
11612027Sjungma@eit.uni-kl.de
11712027Sjungma@eit.uni-kl.de        /** Function to set the pointer for the peer port.
11812027Sjungma@eit.uni-kl.de        @todo should be called by the configuration stuff (python).
11912027Sjungma@eit.uni-kl.de    */
12012027Sjungma@eit.uni-kl.de    Port *getPeer() { return peer; }
12112027Sjungma@eit.uni-kl.de
12212027Sjungma@eit.uni-kl.de  protected:
12312027Sjungma@eit.uni-kl.de
12412027Sjungma@eit.uni-kl.de    /** These functions are protected because they should only be
12512027Sjungma@eit.uni-kl.de     * called by a peer port, never directly by any outside object. */
12612027Sjungma@eit.uni-kl.de
12712027Sjungma@eit.uni-kl.de    /** Called to recive a timing call from the peer port. */
12812027Sjungma@eit.uni-kl.de    virtual bool recvTiming(Packet *pkt) = 0;
12912027Sjungma@eit.uni-kl.de
13012027Sjungma@eit.uni-kl.de    /** Called to recive a atomic call from the peer port. */
13112027Sjungma@eit.uni-kl.de    virtual Tick recvAtomic(Packet *pkt) = 0;
13212027Sjungma@eit.uni-kl.de
13312027Sjungma@eit.uni-kl.de    /** Called to recive a functional call from the peer port. */
13412027Sjungma@eit.uni-kl.de    virtual void recvFunctional(Packet *pkt) = 0;
13512027Sjungma@eit.uni-kl.de
13612027Sjungma@eit.uni-kl.de    /** Called to recieve a status change from the peer port. */
13712027Sjungma@eit.uni-kl.de    virtual void recvStatusChange(Status status) = 0;
13812027Sjungma@eit.uni-kl.de
13912027Sjungma@eit.uni-kl.de    /** Called by a peer port if the send was unsuccesful, and had to
14012027Sjungma@eit.uni-kl.de        wait.  This shouldn't be valid for response paths (IO Devices).
14112027Sjungma@eit.uni-kl.de        so it is set to panic if it isn't already defined.
14212027Sjungma@eit.uni-kl.de    */
14312027Sjungma@eit.uni-kl.de    virtual Packet *recvRetry() { panic("??"); }
14412027Sjungma@eit.uni-kl.de
14512027Sjungma@eit.uni-kl.de    /** Called by a peer port in order to determine the block size of the
14612027Sjungma@eit.uni-kl.de        device connected to this port.  It sometimes doesn't make sense for
14712027Sjungma@eit.uni-kl.de        this function to be called, a DMA interface doesn't really have a
14812027Sjungma@eit.uni-kl.de        block size, so it is defaulted to a panic.
14912027Sjungma@eit.uni-kl.de    */
15012027Sjungma@eit.uni-kl.de    virtual int deviceBlockSize() { panic("??"); }
15112027Sjungma@eit.uni-kl.de
15212027Sjungma@eit.uni-kl.de    /** The peer port is requesting us to reply with a list of the ranges we
15312027Sjungma@eit.uni-kl.de        are responsible for.
15412027Sjungma@eit.uni-kl.de        @param resp is a list of ranges responded to
15512027Sjungma@eit.uni-kl.de        @param snoop is a list of ranges snooped
15612027Sjungma@eit.uni-kl.de    */
15712027Sjungma@eit.uni-kl.de    virtual void getDeviceAddressRanges(AddrRangeList &resp,
15812027Sjungma@eit.uni-kl.de            AddrRangeList &snoop)
15912027Sjungma@eit.uni-kl.de    { panic("??"); }
16012027Sjungma@eit.uni-kl.de
16112027Sjungma@eit.uni-kl.de  public:
16212027Sjungma@eit.uni-kl.de
16312027Sjungma@eit.uni-kl.de    /** Function called by associated memory device (cache, memory, iodevice)
16412027Sjungma@eit.uni-kl.de        in order to send a timing request to the port.  Simply calls the peer
16512027Sjungma@eit.uni-kl.de        port receive function.
16612027Sjungma@eit.uni-kl.de        @return This function returns if the send was succesful in it's
16712027Sjungma@eit.uni-kl.de        recieve. If it was a failure, then the port will wait for a recvRetry
16812027Sjungma@eit.uni-kl.de        at which point it can issue a successful sendTiming.  This is used in
16912027Sjungma@eit.uni-kl.de        case a cache has a higher priority request come in while waiting for
17012027Sjungma@eit.uni-kl.de        the bus to arbitrate.
17112027Sjungma@eit.uni-kl.de    */
17212027Sjungma@eit.uni-kl.de    bool sendTiming(Packet *pkt) { return peer->recvTiming(pkt); }
17312027Sjungma@eit.uni-kl.de
17412027Sjungma@eit.uni-kl.de    /** Function called by the associated device to send an atomic access,
17512027Sjungma@eit.uni-kl.de        an access in which the data is moved and the state is updated in one
17612027Sjungma@eit.uni-kl.de        cycle, without interleaving with other memory accesses.
17712027Sjungma@eit.uni-kl.de    */
17812027Sjungma@eit.uni-kl.de    Tick sendAtomic(Packet *pkt)
17912027Sjungma@eit.uni-kl.de        { return peer->recvAtomic(pkt); }
18012027Sjungma@eit.uni-kl.de
18112027Sjungma@eit.uni-kl.de    /** Function called by the associated device to send a functional access,
18212027Sjungma@eit.uni-kl.de        an access in which the data is instantly updated everywhere in the
18312027Sjungma@eit.uni-kl.de        memory system, without affecting the current state of any block or
18412027Sjungma@eit.uni-kl.de        moving the block.
18512027Sjungma@eit.uni-kl.de    */
18612027Sjungma@eit.uni-kl.de    void sendFunctional(Packet *pkt)
18712027Sjungma@eit.uni-kl.de        { return peer->recvFunctional(pkt); }
18812027Sjungma@eit.uni-kl.de
18912027Sjungma@eit.uni-kl.de    /** Called by the associated device to send a status change to the device
19012027Sjungma@eit.uni-kl.de        connected to the peer interface.
19112027Sjungma@eit.uni-kl.de    */
19212027Sjungma@eit.uni-kl.de    void sendStatusChange(Status status) {peer->recvStatusChange(status); }
19312027Sjungma@eit.uni-kl.de
19412027Sjungma@eit.uni-kl.de    /** When a timing access doesn't return a success, some time later the
19512027Sjungma@eit.uni-kl.de        Retry will be sent.
19612027Sjungma@eit.uni-kl.de    */
19712027Sjungma@eit.uni-kl.de    Packet *sendRetry() { return peer->recvRetry(); }
19812027Sjungma@eit.uni-kl.de
19912027Sjungma@eit.uni-kl.de    /** Called by the associated device if it wishes to find out the blocksize
20012027Sjungma@eit.uni-kl.de        of the device on attached to the peer port.
20112027Sjungma@eit.uni-kl.de    */
20212027Sjungma@eit.uni-kl.de    int peerBlockSize() { return peer->deviceBlockSize(); }
20312027Sjungma@eit.uni-kl.de
20412027Sjungma@eit.uni-kl.de    /** Called by the associated device if it wishes to find out the address
20512027Sjungma@eit.uni-kl.de        ranges connected to the peer ports devices.
20612027Sjungma@eit.uni-kl.de    */
20712027Sjungma@eit.uni-kl.de    void getPeerAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
20812027Sjungma@eit.uni-kl.de    { peer->getDeviceAddressRanges(resp, snoop); }
20912027Sjungma@eit.uni-kl.de
21012027Sjungma@eit.uni-kl.de    /** This function is a wrapper around sendFunctional()
21112027Sjungma@eit.uni-kl.de        that breaks a larger, arbitrarily aligned access into
21212027Sjungma@eit.uni-kl.de        appropriate chunks.  The default implementation can use
21312027Sjungma@eit.uni-kl.de        getBlockSize() to determine the block size and go from there.
21412027Sjungma@eit.uni-kl.de    */
21512027Sjungma@eit.uni-kl.de    virtual void readBlob(Addr addr, uint8_t *p, int size);
21612027Sjungma@eit.uni-kl.de
21712027Sjungma@eit.uni-kl.de    /** This function is a wrapper around sendFunctional()
21812027Sjungma@eit.uni-kl.de        that breaks a larger, arbitrarily aligned access into
21912027Sjungma@eit.uni-kl.de        appropriate chunks.  The default implementation can use
22012027Sjungma@eit.uni-kl.de        getBlockSize() to determine the block size and go from there.
22112027Sjungma@eit.uni-kl.de    */
22212027Sjungma@eit.uni-kl.de    virtual void writeBlob(Addr addr, uint8_t *p, int size);
22312027Sjungma@eit.uni-kl.de
22412027Sjungma@eit.uni-kl.de    /** Fill size bytes starting at addr with byte value val.  This
22512027Sjungma@eit.uni-kl.de        should not need to be virtual, since it can be implemented in
22612027Sjungma@eit.uni-kl.de        terms of writeBlob().  However, it shouldn't be
22712027Sjungma@eit.uni-kl.de        performance-critical either, so it could be if we wanted to.
22812027Sjungma@eit.uni-kl.de    */
22912027Sjungma@eit.uni-kl.de    virtual void memsetBlob(Addr addr, uint8_t val, int size);
23012027Sjungma@eit.uni-kl.de
23112027Sjungma@eit.uni-kl.de  private:
23212027Sjungma@eit.uni-kl.de
23312027Sjungma@eit.uni-kl.de    /** Internal helper function for read/writeBlob().
23412027Sjungma@eit.uni-kl.de     */
23512027Sjungma@eit.uni-kl.de    void blobHelper(Addr addr, uint8_t *p, int size, Packet::Command cmd);
23612027Sjungma@eit.uni-kl.de};
23712027Sjungma@eit.uni-kl.de
23812027Sjungma@eit.uni-kl.de/** A simple functional port that is only meant for one way communication to
23912027Sjungma@eit.uni-kl.de * physical memory. It is only meant to be used to load data into memory before
24012027Sjungma@eit.uni-kl.de * the simulation begins.
24112027Sjungma@eit.uni-kl.de */
24212027Sjungma@eit.uni-kl.de
24312027Sjungma@eit.uni-kl.declass FunctionalPort : public Port
24412027Sjungma@eit.uni-kl.de{
24512027Sjungma@eit.uni-kl.de  public:
24612027Sjungma@eit.uni-kl.de    FunctionalPort(const std::string &_name)
24712027Sjungma@eit.uni-kl.de        : Port(_name)
24812027Sjungma@eit.uni-kl.de    {}
24912027Sjungma@eit.uni-kl.de
25012027Sjungma@eit.uni-kl.de    virtual bool recvTiming(Packet *pkt) { panic("FuncPort is UniDir"); }
25112027Sjungma@eit.uni-kl.de    virtual Tick recvAtomic(Packet *pkt) { panic("FuncPort is UniDir"); }
25212027Sjungma@eit.uni-kl.de    virtual void recvFunctional(Packet *pkt) { panic("FuncPort is UniDir"); }
25312027Sjungma@eit.uni-kl.de    virtual void recvStatusChange(Status status) {}
25412027Sjungma@eit.uni-kl.de
25512027Sjungma@eit.uni-kl.de    template <typename T>
25612027Sjungma@eit.uni-kl.de    inline void write(Addr addr, T d)
25712027Sjungma@eit.uni-kl.de    {
25812027Sjungma@eit.uni-kl.de        writeBlob(addr, (uint8_t*)&d, sizeof(T));
25912027Sjungma@eit.uni-kl.de    }
26012027Sjungma@eit.uni-kl.de
26112027Sjungma@eit.uni-kl.de    template <typename T>
26212027Sjungma@eit.uni-kl.de    inline T read(Addr addr)
26312027Sjungma@eit.uni-kl.de    {
26412027Sjungma@eit.uni-kl.de        T d;
26512027Sjungma@eit.uni-kl.de        readBlob(addr, (uint8_t*)&d, sizeof(T));
26612027Sjungma@eit.uni-kl.de        return d;
26712027Sjungma@eit.uni-kl.de    }
26812027Sjungma@eit.uni-kl.de};
26912027Sjungma@eit.uni-kl.de
27012027Sjungma@eit.uni-kl.de#endif //__MEM_PORT_HH__
27112027Sjungma@eit.uni-kl.de