packet.hh revision 12334:e0ab29a34764
12810SN/A/*
29614Srene.dejong@arm.com * Copyright (c) 2012-2016 ARM Limited
38856Sandreas.hansson@arm.com * All rights reserved
48856Sandreas.hansson@arm.com *
58856Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
68856Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
78856Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
88856Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
98856Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
108856Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
118856Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
128856Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
138856Sandreas.hansson@arm.com *
142810SN/A * Copyright (c) 2006 The Regents of The University of Michigan
152810SN/A * Copyright (c) 2010,2015 Advanced Micro Devices, Inc.
162810SN/A * All rights reserved.
172810SN/A *
182810SN/A * Redistribution and use in source and binary forms, with or without
192810SN/A * modification, are permitted provided that the following conditions are
202810SN/A * met: redistributions of source code must retain the above copyright
212810SN/A * notice, this list of conditions and the following disclaimer;
222810SN/A * redistributions in binary form must reproduce the above copyright
232810SN/A * notice, this list of conditions and the following disclaimer in the
242810SN/A * documentation and/or other materials provided with the distribution;
252810SN/A * neither the name of the copyright holders nor the names of its
262810SN/A * contributors may be used to endorse or promote products derived from
272810SN/A * this software without specific prior written permission.
282810SN/A *
292810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
302810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
312810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
322810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
332810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
342810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
352810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
362810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
372810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
382810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
392810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
402810SN/A *
412810SN/A * Authors: Ron Dreslinski
422810SN/A *          Steve Reinhardt
432810SN/A *          Ali Saidi
442810SN/A *          Andreas Hansson
452810SN/A */
462810SN/A
472810SN/A/**
488232Snate@binkert.org * @file
499152Satgutier@umich.edu * Declaration of the Packet class.
509795Sandreas.hansson@arm.com */
519795Sandreas.hansson@arm.com
5210263Satgutier@umich.edu#ifndef __MEM_PACKET_HH__
535338Sstever@gmail.com#define __MEM_PACKET_HH__
549795Sandreas.hansson@arm.com
555338Sstever@gmail.com#include <bitset>
568786Sgblack@eecs.umich.edu#include <cassert>
572810SN/A#include <list>
582810SN/A
592810SN/A#include "base/cast.hh"
608856Sandreas.hansson@arm.com#include "base/compiler.hh"
618856Sandreas.hansson@arm.com#include "base/flags.hh"
628856Sandreas.hansson@arm.com#include "base/logging.hh"
638922Swilliam.wang@arm.com#include "base/printable.hh"
648914Sandreas.hansson@arm.com#include "base/types.hh"
658856Sandreas.hansson@arm.com#include "mem/request.hh"
668856Sandreas.hansson@arm.com#include "sim/core.hh"
674475SN/A
6811053Sandreas.hansson@arm.comclass Packet;
695034SN/Atypedef Packet *PacketPtr;
7010360Sandreas.hansson@arm.comtypedef uint8_t* PacketDataPtr;
7111377Sandreas.hansson@arm.comtypedef std::list<PacketPtr> PacketList;
7211377Sandreas.hansson@arm.com
7311053Sandreas.hansson@arm.comclass MemCmd
7410693SMarco.Balboni@ARM.com{
7510693SMarco.Balboni@ARM.com    friend class Packet;
7610693SMarco.Balboni@ARM.com
779263Smrinmoy.ghosh@arm.com  public:
785034SN/A    /**
7911331Sandreas.hansson@arm.com     * List of all commands associated with a packet.
8010884Sandreas.hansson@arm.com     */
814626SN/A    enum Command
8210360Sandreas.hansson@arm.com    {
834626SN/A        InvalidCmd,
845034SN/A        ReadReq,
858883SAli.Saidi@ARM.com        ReadResp,
868833Sdam.sunwoo@arm.com        ReadRespWithInvalidate,
874458SN/A        WriteReq,
8811377Sandreas.hansson@arm.com        WriteResp,
8911377Sandreas.hansson@arm.com        WritebackDirty,
9011377Sandreas.hansson@arm.com        WritebackClean,
9111377Sandreas.hansson@arm.com        CleanEvict,
9211377Sandreas.hansson@arm.com        SoftPFReq,
9311377Sandreas.hansson@arm.com        HardPFReq,
9411331Sandreas.hansson@arm.com        SoftPFResp,
9511331Sandreas.hansson@arm.com        HardPFResp,
962810SN/A        WriteLineReq,
972810SN/A        UpgradeReq,
983013SN/A        SCUpgradeReq,           // Special "weak" upgrade for StoreCond
998856Sandreas.hansson@arm.com        UpgradeResp,
1002810SN/A        SCUpgradeFailReq,       // Failed SCUpgradeReq in MSHR (never sent)
1013013SN/A        UpgradeFailResp,        // Valid for SCUpgradeReq only
10210714Sandreas.hansson@arm.com        ReadExReq,
1032810SN/A        ReadExResp,
1049614Srene.dejong@arm.com        ReadCleanReq,
1059614Srene.dejong@arm.com        ReadSharedReq,
1069614Srene.dejong@arm.com        LoadLockedReq,
10710345SCurtis.Dunham@arm.com        StoreCondReq,
10810714Sandreas.hansson@arm.com        StoreCondFailReq,       // Failed StoreCondReq in MSHR (never sent)
10910345SCurtis.Dunham@arm.com        StoreCondResp,
1109614Srene.dejong@arm.com        SwapReq,
1112810SN/A        SwapResp,
1122810SN/A        MessageReq,
1132810SN/A        MessageResp,
1148856Sandreas.hansson@arm.com        MemFenceReq,
1152810SN/A        MemFenceResp,
1163013SN/A        // Error responses
11710714Sandreas.hansson@arm.com        // @TODO these should be classified as responses rather than
1183013SN/A        // requests; coding them as requests initially for backwards
1198856Sandreas.hansson@arm.com        // compatibility
12010714Sandreas.hansson@arm.com        InvalidDestError,  // packet dest field invalid
1218922Swilliam.wang@arm.com        BadAddressError,   // memory address invalid
1222897SN/A        FunctionalReadError, // unable to fulfill functional read
1232810SN/A        FunctionalWriteError, // unable to fulfill functional write
1242810SN/A        // Fake simulator-only commands
12510344Sandreas.hansson@arm.com        PrintReq,       // Print state matching address
12610344Sandreas.hansson@arm.com        FlushReq,      //request for a cache flush
12710344Sandreas.hansson@arm.com        InvalidateReq,   // request for address to be invalidated
12810714Sandreas.hansson@arm.com        InvalidateResp,
12910344Sandreas.hansson@arm.com        NUM_MEM_CMDS
13010344Sandreas.hansson@arm.com    };
13110344Sandreas.hansson@arm.com
13210713Sandreas.hansson@arm.com  private:
13310344Sandreas.hansson@arm.com    /**
1342844SN/A     * List of command attributes.
1352810SN/A     */
1362858SN/A    enum Attribute
1372858SN/A    {
1388856Sandreas.hansson@arm.com        IsRead,         //!< Data flows from responder to requester
1398922Swilliam.wang@arm.com        IsWrite,        //!< Data flows from requester to responder
1408711Sandreas.hansson@arm.com        IsUpgrade,
14111331Sandreas.hansson@arm.com        IsInvalidate,
1422858SN/A        NeedsWritable,  //!< Requires writable copy to complete in-cache
1432858SN/A        IsRequest,      //!< Issued by requester
1449294Sandreas.hansson@arm.com        IsResponse,     //!< Issue by responder
1459294Sandreas.hansson@arm.com        NeedsResponse,  //!< Requester needs response from target
1468922Swilliam.wang@arm.com        IsEviction,
1478922Swilliam.wang@arm.com        IsSWPrefetch,
1488922Swilliam.wang@arm.com        IsHWPrefetch,
1498922Swilliam.wang@arm.com        IsLlsc,         //!< Alpha/MIPS LL or SC access
1508922Swilliam.wang@arm.com        HasData,        //!< There is an associated payload
1518922Swilliam.wang@arm.com        IsError,        //!< Error response
1528922Swilliam.wang@arm.com        IsPrint,        //!< Print state matching address (for debugging)
1538922Swilliam.wang@arm.com        IsFlush,        //!< Flush the address from caches
1549294Sandreas.hansson@arm.com        FromCache,      //!< Request originated from a caching agent
1559294Sandreas.hansson@arm.com        NUM_COMMAND_ATTRIBUTES
1568922Swilliam.wang@arm.com    };
1578922Swilliam.wang@arm.com
1588922Swilliam.wang@arm.com    /**
1598922Swilliam.wang@arm.com     * Structure that defines attributes and other data associated
1608922Swilliam.wang@arm.com     * with a Command.
1618922Swilliam.wang@arm.com     */
1628922Swilliam.wang@arm.com    struct CommandInfo
1634628SN/A    {
16410821Sandreas.hansson@arm.com        /// Set of attribute flags.
16510821Sandreas.hansson@arm.com        const std::bitset<NUM_COMMAND_ATTRIBUTES> attributes;
16610821Sandreas.hansson@arm.com        /// Corresponding response for requests; InvalidCmd if no
16710821Sandreas.hansson@arm.com        /// response is applicable.
16810821Sandreas.hansson@arm.com        const Command response;
16910821Sandreas.hansson@arm.com        /// String representation (for printing)
17010821Sandreas.hansson@arm.com        const std::string str;
17110821Sandreas.hansson@arm.com    };
17210821Sandreas.hansson@arm.com
17310821Sandreas.hansson@arm.com    /// Array to map Command enum to associated info.
17410821Sandreas.hansson@arm.com    static const CommandInfo commandInfo[];
1752858SN/A
1762810SN/A  private:
1772810SN/A
1782810SN/A    Command cmd;
1792810SN/A
1802810SN/A    bool
1814022SN/A    testCmdAttrib(MemCmd::Attribute attrib) const
1824022SN/A    {
1834022SN/A        return commandInfo[cmd].attributes[attrib] != 0;
1842810SN/A    }
1852810SN/A
1868833Sdam.sunwoo@arm.com  public:
1872810SN/A
1882810SN/A    bool isRead() const            { return testCmdAttrib(IsRead); }
1892810SN/A    bool isWrite() const           { return testCmdAttrib(IsWrite); }
1902810SN/A    bool isUpgrade() const         { return testCmdAttrib(IsUpgrade); }
1918833Sdam.sunwoo@arm.com    bool isRequest() const         { return testCmdAttrib(IsRequest); }
1928833Sdam.sunwoo@arm.com    bool isResponse() const        { return testCmdAttrib(IsResponse); }
1938833Sdam.sunwoo@arm.com    bool needsWritable() const     { return testCmdAttrib(NeedsWritable); }
1942810SN/A    bool needsResponse() const     { return testCmdAttrib(NeedsResponse); }
1952810SN/A    bool isInvalidate() const      { return testCmdAttrib(IsInvalidate); }
1964871SN/A    bool isEviction() const        { return testCmdAttrib(IsEviction); }
1974871SN/A    bool fromCache() const         { return testCmdAttrib(FromCache); }
1984871SN/A
1994871SN/A    /**
20010885Sandreas.hansson@arm.com     * A writeback is an eviction that carries data.
20110885Sandreas.hansson@arm.com     */
2024871SN/A    bool isWriteback() const       { return testCmdAttrib(IsEviction) &&
2034871SN/A                                            testCmdAttrib(HasData); }
2044871SN/A
2054871SN/A    /**
2064871SN/A     * Check if this particular packet type carries payload data. Note
2072810SN/A     * that this does not reflect if the data pointer of the packet is
2082810SN/A     * valid or not.
2092810SN/A     */
2108833Sdam.sunwoo@arm.com    bool hasData() const        { return testCmdAttrib(HasData); }
2112810SN/A    bool isLLSC() const         { return testCmdAttrib(IsLlsc); }
2124871SN/A    bool isSWPrefetch() const   { return testCmdAttrib(IsSWPrefetch); }
2138833Sdam.sunwoo@arm.com    bool isHWPrefetch() const   { return testCmdAttrib(IsHWPrefetch); }
2148833Sdam.sunwoo@arm.com    bool isPrefetch() const     { return testCmdAttrib(IsSWPrefetch) ||
2158833Sdam.sunwoo@arm.com                                         testCmdAttrib(IsHWPrefetch); }
2162810SN/A    bool isError() const        { return testCmdAttrib(IsError); }
2172810SN/A    bool isPrint() const        { return testCmdAttrib(IsPrint); }
2182810SN/A    bool isFlush() const        { return testCmdAttrib(IsFlush); }
2192810SN/A
2208833Sdam.sunwoo@arm.com    Command
2212810SN/A    responseCommand() const
2224871SN/A    {
2238833Sdam.sunwoo@arm.com        return commandInfo[cmd].response;
2248833Sdam.sunwoo@arm.com    }
2258833Sdam.sunwoo@arm.com
2262810SN/A    /// Return the string to a cmd given by idx.
2272810SN/A    const std::string &toString() const { return commandInfo[cmd].str; }
2284022SN/A    int toInt() const { return (int)cmd; }
2294022SN/A
2304022SN/A    MemCmd(Command _cmd) : cmd(_cmd) { }
2312810SN/A    MemCmd(int _cmd) : cmd((Command)_cmd) { }
2322810SN/A    MemCmd() : cmd(InvalidCmd) { }
2338833Sdam.sunwoo@arm.com
2342810SN/A    bool operator==(MemCmd c2) const { return (cmd == c2.cmd); }
2352810SN/A    bool operator!=(MemCmd c2) const { return (cmd != c2.cmd); }
2362810SN/A};
2372810SN/A
2388833Sdam.sunwoo@arm.com/**
2398833Sdam.sunwoo@arm.com * A Packet is used to encapsulate a transfer between two objects in
2408833Sdam.sunwoo@arm.com * the memory system (e.g., the L1 and L2 cache).  (In contrast, a
2412810SN/A * single Request travels all the way from the requester to the
2422810SN/A * ultimate destination and back, possibly being conveyed by several
2432810SN/A * different Packets along the way.)
2442810SN/A */
2452810SN/Aclass Packet : public Printable
2468833Sdam.sunwoo@arm.com{
2472810SN/A  public:
2484871SN/A    typedef uint32_t FlagsType;
2498833Sdam.sunwoo@arm.com    typedef ::Flags<FlagsType> Flags;
2508833Sdam.sunwoo@arm.com
2518833Sdam.sunwoo@arm.com  private:
2522810SN/A
2532810SN/A    enum : FlagsType {
2542810SN/A        // Flags to transfer across when copying a packet
2552810SN/A        COPY_FLAGS             = 0x0000000F,
2568833Sdam.sunwoo@arm.com
2572810SN/A        // Does this packet have sharers (which means it should not be
2584871SN/A        // considered writable) or not. See setHasSharers below.
2598833Sdam.sunwoo@arm.com        HAS_SHARERS            = 0x00000001,
2608833Sdam.sunwoo@arm.com
2618833Sdam.sunwoo@arm.com        // Special control flags
2622810SN/A        /// Special timing-mode atomic snoop for multi-level coherence.
2632810SN/A        EXPRESS_SNOOP          = 0x00000002,
2644022SN/A
2654022SN/A        /// Allow a responding cache to inform the cache hierarchy
2664022SN/A        /// that it had a writable copy before responding. See
2672810SN/A        /// setResponderHadWritable below.
2682810SN/A        RESPONDER_HAD_WRITABLE = 0x00000004,
2698833Sdam.sunwoo@arm.com
2702810SN/A        // Snoop co-ordination flag to indicate that a cache is
2712810SN/A        // responding to a snoop. See setCacheResponding below.
2722810SN/A        CACHE_RESPONDING       = 0x00000008,
2732810SN/A
2748833Sdam.sunwoo@arm.com        /// Are the 'addr' and 'size' fields valid?
2758833Sdam.sunwoo@arm.com        VALID_ADDR             = 0x00000100,
2768833Sdam.sunwoo@arm.com        VALID_SIZE             = 0x00000200,
2772810SN/A
2782810SN/A        /// Is the data pointer set to a value that shouldn't be freed
2792810SN/A        /// when the packet is destroyed?
2802810SN/A        STATIC_DATA            = 0x00001000,
2812810SN/A        /// The data pointer points to a value that should be freed when
2828833Sdam.sunwoo@arm.com        /// the packet is destroyed. The pointer is assumed to be pointing
2832810SN/A        /// to an array, and delete [] is consequently called
2844871SN/A        DYNAMIC_DATA           = 0x00002000,
2858833Sdam.sunwoo@arm.com
2868833Sdam.sunwoo@arm.com        /// suppress the error if this packet encounters a functional
2878833Sdam.sunwoo@arm.com        /// access failure.
2882810SN/A        SUPPRESS_FUNC_ERROR    = 0x00008000,
2892810SN/A
2902810SN/A        // Signal block present to squash prefetch and cache evict packets
2912810SN/A        // through express snoop flag
2928833Sdam.sunwoo@arm.com        BLOCK_CACHED          = 0x00010000
2932810SN/A    };
2944871SN/A
2958833Sdam.sunwoo@arm.com    Flags flags;
2968833Sdam.sunwoo@arm.com
2978833Sdam.sunwoo@arm.com  public:
2982810SN/A    typedef MemCmd::Command Command;
2992810SN/A
3004022SN/A    /// The command field of the packet.
3014022SN/A    MemCmd cmd;
3024022SN/A
3032810SN/A    /// A pointer to the original request.
3042810SN/A    const RequestPtr req;
3052810SN/A
3062810SN/A  private:
3072810SN/A   /**
3082810SN/A    * A pointer to the data being transfered.  It can be differnt
3098833Sdam.sunwoo@arm.com    * sizes at each level of the heirarchy so it belongs in the
3102810SN/A    * packet, not request. This may or may not be populated when a
3118833Sdam.sunwoo@arm.com    * responder recieves the packet. If not populated it memory should
3128833Sdam.sunwoo@arm.com    * be allocated.
3138833Sdam.sunwoo@arm.com    */
3142810SN/A    PacketDataPtr data;
3152810SN/A
3162810SN/A    /// The address of the request.  This address could be virtual or
3172810SN/A    /// physical, depending on the system configuration.
3182810SN/A    Addr addr;
3198833Sdam.sunwoo@arm.com
3202810SN/A    /// True if the request targets the secure memory space.
3212810SN/A    bool _isSecure;
3228833Sdam.sunwoo@arm.com
3238833Sdam.sunwoo@arm.com    /// The size of the request or transfer.
3248833Sdam.sunwoo@arm.com    unsigned size;
3252810SN/A
3262810SN/A    /**
3272810SN/A     * Track the bytes found that satisfy a functional read.
3282810SN/A     */
3298833Sdam.sunwoo@arm.com    std::vector<bool> bytesValid;
3302810SN/A
3312810SN/A  public:
3328833Sdam.sunwoo@arm.com
3338833Sdam.sunwoo@arm.com    /**
3348833Sdam.sunwoo@arm.com     * The extra delay from seeing the packet until the header is
3352810SN/A     * transmitted. This delay is used to communicate the crossbar
3362810SN/A     * forwarding latency to the neighbouring object (e.g. a cache)
3374022SN/A     * that actually makes the packet wait. As the delay is relative,
3384022SN/A     * a 32-bit unsigned should be sufficient.
3394022SN/A     */
3402810SN/A    uint32_t headerDelay;
3412810SN/A
3422810SN/A    /**
3432810SN/A     * Keep track of the extra delay incurred by snooping upwards
3442810SN/A     * before sending a request down the memory system. This is used
3452810SN/A     * by the coherent crossbar to account for the additional request
3468833Sdam.sunwoo@arm.com     * delay.
3472810SN/A     */
3488833Sdam.sunwoo@arm.com    uint32_t snoopDelay;
3498833Sdam.sunwoo@arm.com
3508833Sdam.sunwoo@arm.com    /**
3512810SN/A     * The extra pipelining delay from seeing the packet until the end of
3522810SN/A     * payload is transmitted by the component that provided it (if
3532810SN/A     * any). This includes the header delay. Similar to the header
3542810SN/A     * delay, this is used to make up for the fact that the
3552810SN/A     * crossbar does not make the packet wait. As the delay is
3568833Sdam.sunwoo@arm.com     * relative, a 32-bit unsigned should be sufficient.
3572810SN/A     */
3582810SN/A    uint32_t payloadDelay;
3598833Sdam.sunwoo@arm.com
3608833Sdam.sunwoo@arm.com    /**
3618833Sdam.sunwoo@arm.com     * A virtual base opaque structure used to hold state associated
3622810SN/A     * with the packet (e.g., an MSHR), specific to a MemObject that
3632810SN/A     * sees the packet. A pointer to this state is returned in the
3642810SN/A     * packet's response so that the MemObject in question can quickly
3652810SN/A     * look up the state needed to process it. A specific subclass
3668833Sdam.sunwoo@arm.com     * would be derived from this to carry state specific to a
3672810SN/A     * particular sending device.
3682810SN/A     *
3698833Sdam.sunwoo@arm.com     * As multiple MemObjects may add their SenderState throughout the
3708833Sdam.sunwoo@arm.com     * memory system, the SenderStates create a stack, where a
3718833Sdam.sunwoo@arm.com     * MemObject can add a new Senderstate, as long as the
3722810SN/A     * predecessing SenderState is restored when the response comes
3732810SN/A     * back. For this reason, the predecessor should always be
3744022SN/A     * populated with the current SenderState of a packet before
3754022SN/A     * modifying the senderState field in the request packet.
3764022SN/A     */
3772810SN/A    struct SenderState
3782810SN/A    {
3792810SN/A        SenderState* predecessor;
3802810SN/A        SenderState() : predecessor(NULL) {}
3812810SN/A        virtual ~SenderState() {}
3822810SN/A    };
3832810SN/A
3842810SN/A    /**
3858833Sdam.sunwoo@arm.com     * Object used to maintain state of a PrintReq.  The senderState
3868833Sdam.sunwoo@arm.com     * field of a PrintReq should always be of this type.
3878833Sdam.sunwoo@arm.com     */
3888833Sdam.sunwoo@arm.com    class PrintReqState : public SenderState
3892810SN/A    {
3902810SN/A      private:
3912810SN/A        /**
3922810SN/A         * An entry in the label stack.
3932810SN/A         */
3948833Sdam.sunwoo@arm.com        struct LabelStackEntry
3952810SN/A        {
3962810SN/A            const std::string label;
3978833Sdam.sunwoo@arm.com            std::string *prefix;
3988833Sdam.sunwoo@arm.com            bool labelPrinted;
3998833Sdam.sunwoo@arm.com            LabelStackEntry(const std::string &_label, std::string *_prefix);
4002810SN/A        };
4012810SN/A
4022810SN/A        typedef std::list<LabelStackEntry> LabelStack;
4032810SN/A        LabelStack labelStack;
4048833Sdam.sunwoo@arm.com
4052810SN/A        std::string *curPrefixPtr;
4062810SN/A
4078833Sdam.sunwoo@arm.com      public:
4088833Sdam.sunwoo@arm.com        std::ostream &os;
4098833Sdam.sunwoo@arm.com        const int verbosity;
4102810SN/A
4112810SN/A        PrintReqState(std::ostream &os, int verbosity = 0);
4122810SN/A        ~PrintReqState();
4132810SN/A
4142810SN/A        /**
4152810SN/A         * Returns the current line prefix.
4162810SN/A         */
4172810SN/A        const std::string &curPrefix() { return *curPrefixPtr; }
4182810SN/A
4192810SN/A        /**
4202810SN/A         * Push a label onto the label stack, and prepend the given
4212810SN/A         * prefix string onto the current prefix.  Labels will only be
4222810SN/A         * printed if an object within the label's scope is printed.
4232810SN/A         */
4242810SN/A        void pushLabel(const std::string &lbl,
4252810SN/A                       const std::string &prefix = "  ");
4262810SN/A
4272810SN/A        /**
4282810SN/A         * Pop a label off the label stack.
4292810SN/A         */
4302810SN/A        void popLabel();
4312810SN/A
4322810SN/A        /**
4332810SN/A         * Print all of the pending unprinted labels on the
4342810SN/A         * stack. Called by printObj(), so normally not called by
4352810SN/A         * users unless bypassing printObj().
4362810SN/A         */
4372810SN/A        void printLabels();
4382810SN/A
4392810SN/A        /**
4402810SN/A         * Print a Printable object to os, because it matched the
4412810SN/A         * address on a PrintReq.
4422810SN/A         */
4432810SN/A        void printObj(Printable *obj);
4442810SN/A    };
4452810SN/A
4462826SN/A    /**
44711436SRekai.GonzalezAlberquilla@arm.com     * This packet's sender state.  Devices should use dynamic_cast<>
44811436SRekai.GonzalezAlberquilla@arm.com     * to cast to the state appropriate to the sender.  The intent of
44911436SRekai.GonzalezAlberquilla@arm.com     * this variable is to allow a device to attach extra information
45011436SRekai.GonzalezAlberquilla@arm.com     * to a request. A response packet must return the sender state
45111436SRekai.GonzalezAlberquilla@arm.com     * that was attached to the original request (even if a new packet
45211436SRekai.GonzalezAlberquilla@arm.com     * is created).
4534626SN/A     */
4548833Sdam.sunwoo@arm.com    SenderState *senderState;
4554626SN/A
4564626SN/A    /**
4578833Sdam.sunwoo@arm.com     * Push a new sender state to the packet and make the current
4584626SN/A     * sender state the predecessor of the new one. This should be
4598833Sdam.sunwoo@arm.com     * prefered over direct manipulation of the senderState member
4608833Sdam.sunwoo@arm.com     * variable.
4618833Sdam.sunwoo@arm.com     *
4624626SN/A     * @param sender_state SenderState to push at the top of the stack
4634626SN/A     */
4644626SN/A    void pushSenderState(SenderState *sender_state);
4654626SN/A
4664626SN/A    /**
4674626SN/A     * Pop the top of the state stack and return a pointer to it. This
4684626SN/A     * assumes the current sender state is not NULL. This should be
4694626SN/A     * preferred over direct manipulation of the senderState member
4708833Sdam.sunwoo@arm.com     * variable.
4714626SN/A     *
4724626SN/A     * @return The current top of the stack
4734626SN/A     */
4744626SN/A    SenderState *popSenderState();
4758833Sdam.sunwoo@arm.com
4768833Sdam.sunwoo@arm.com    /**
4778833Sdam.sunwoo@arm.com     * Go through the sender state stack and return the first instance
4784626SN/A     * that is of type T (as determined by a dynamic_cast). If there
4794626SN/A     * is no sender state of type T, NULL is returned.
4804626SN/A     *
4814626SN/A     * @return The topmost state of type T
4824626SN/A     */
4838833Sdam.sunwoo@arm.com    template <typename T>
4844626SN/A    T * findNextSenderState() const
4854871SN/A    {
4868833Sdam.sunwoo@arm.com        T *t = NULL;
4878833Sdam.sunwoo@arm.com        SenderState* sender_state = senderState;
4888833Sdam.sunwoo@arm.com        while (t == NULL && sender_state != NULL) {
4894626SN/A            t = dynamic_cast<T*>(sender_state);
4904626SN/A            sender_state = sender_state->predecessor;
4914626SN/A        }
4924626SN/A        return t;
4938833Sdam.sunwoo@arm.com    }
4944626SN/A
4954871SN/A    /// Return the string name of the cmd field (for debugging and
4968833Sdam.sunwoo@arm.com    /// tracing).
4978833Sdam.sunwoo@arm.com    const std::string &cmdString() const { return cmd.toString(); }
4988833Sdam.sunwoo@arm.com
4994626SN/A    /// Return the index of this command.
5004626SN/A    inline int cmdToIndex() const { return cmd.toInt(); }
5014626SN/A
5024626SN/A    bool isRead() const              { return cmd.isRead(); }
5034626SN/A    bool isWrite() const             { return cmd.isWrite(); }
5044626SN/A    bool isUpgrade()  const          { return cmd.isUpgrade(); }
5054626SN/A    bool isRequest() const           { return cmd.isRequest(); }
5068833Sdam.sunwoo@arm.com    bool isResponse() const          { return cmd.isResponse(); }
5074626SN/A    bool needsWritable() const
5084626SN/A    {
5094626SN/A        // we should never check if a response needsWritable, the
5104626SN/A        // request has this flag, and for a response we should rather
5118833Sdam.sunwoo@arm.com        // look at the hasSharers flag (if not set, the response is to
5128833Sdam.sunwoo@arm.com        // be considered writable)
5138833Sdam.sunwoo@arm.com        assert(isRequest());
5144626SN/A        return cmd.needsWritable();
5154626SN/A    }
5164626SN/A    bool needsResponse() const       { return cmd.needsResponse(); }
5174626SN/A    bool isInvalidate() const        { return cmd.isInvalidate(); }
5184626SN/A    bool isEviction() const          { return cmd.isEviction(); }
5198833Sdam.sunwoo@arm.com    bool fromCache() const           { return cmd.fromCache(); }
5204626SN/A    bool isWriteback() const         { return cmd.isWriteback(); }
5214871SN/A    bool hasData() const             { return cmd.hasData(); }
5228833Sdam.sunwoo@arm.com    bool hasRespData() const
5238833Sdam.sunwoo@arm.com    {
5248833Sdam.sunwoo@arm.com        MemCmd resp_cmd = cmd.responseCommand();
5254626SN/A        return resp_cmd.hasData();
5264626SN/A    }
5274626SN/A    bool isLLSC() const              { return cmd.isLLSC(); }
5284626SN/A    bool isError() const             { return cmd.isError(); }
5298833Sdam.sunwoo@arm.com    bool isPrint() const             { return cmd.isPrint(); }
5304626SN/A    bool isFlush() const             { return cmd.isFlush(); }
5314871SN/A
5328833Sdam.sunwoo@arm.com    //@{
5338833Sdam.sunwoo@arm.com    /// Snoop flags
5348833Sdam.sunwoo@arm.com    /**
5354626SN/A     * Set the cacheResponding flag. This is used by the caches to
5364626SN/A     * signal another cache that they are responding to a request. A
5374626SN/A     * cache will only respond to snoops if it has the line in either
5384626SN/A     * Modified or Owned state. Note that on snoop hits we always pass
5394626SN/A     * the line as Modified and never Owned. In the case of an Owned
5404626SN/A     * line we proceed to invalidate all other copies.
5414626SN/A     *
5428833Sdam.sunwoo@arm.com     * On a cache fill (see Cache::handleFill), we check hasSharers
5434626SN/A     * first, ignoring the cacheResponding flag if hasSharers is set.
5444626SN/A     * A line is consequently allocated as:
5454626SN/A     *
5464626SN/A     * hasSharers cacheResponding state
5478833Sdam.sunwoo@arm.com     * true       false           Shared
5488833Sdam.sunwoo@arm.com     * true       true            Shared
5498833Sdam.sunwoo@arm.com     * false      false           Exclusive
5504626SN/A     * false      true            Modified
5514626SN/A     */
5524626SN/A    void setCacheResponding()
5534626SN/A    {
5544626SN/A        assert(isRequest());
5558833Sdam.sunwoo@arm.com        assert(!flags.isSet(CACHE_RESPONDING));
5564626SN/A        flags.set(CACHE_RESPONDING);
5574871SN/A    }
5588833Sdam.sunwoo@arm.com    bool cacheResponding() const { return flags.isSet(CACHE_RESPONDING); }
5598833Sdam.sunwoo@arm.com    /**
5608833Sdam.sunwoo@arm.com     * On fills, the hasSharers flag is used by the caches in
5614626SN/A     * combination with the cacheResponding flag, as clarified
5624626SN/A     * above. If the hasSharers flag is not set, the packet is passing
5634626SN/A     * writable. Thus, a response from a memory passes the line as
5644626SN/A     * writable by default.
5658833Sdam.sunwoo@arm.com     *
5664626SN/A     * The hasSharers flag is also used by upstream caches to inform a
5674871SN/A     * downstream cache that they have the block (by calling
5684871SN/A     * setHasSharers on snoop request packets that hit in upstream
5698833Sdam.sunwoo@arm.com     * cachs tags or MSHRs). If the snoop packet has sharers, a
5708833Sdam.sunwoo@arm.com     * downstream cache is prevented from passing a dirty line upwards
5718833Sdam.sunwoo@arm.com     * if it was not explicitly asked for a writable copy. See
5724626SN/A     * Cache::satisfyCpuSideRequest.
5734626SN/A     *
5744626SN/A     * The hasSharers flag is also used on writebacks, in
5754626SN/A     * combination with the WritbackClean or WritebackDirty commands,
5764626SN/A     * to allocate the block downstream either as:
5774626SN/A     *
5784626SN/A     * command        hasSharers state
5798833Sdam.sunwoo@arm.com     * WritebackDirty false      Modified
5804626SN/A     * WritebackDirty true       Owned
5814626SN/A     * WritebackClean false      Exclusive
5824626SN/A     * WritebackClean true       Shared
5834626SN/A     */
5848833Sdam.sunwoo@arm.com    void setHasSharers()    { flags.set(HAS_SHARERS); }
5858833Sdam.sunwoo@arm.com    bool hasSharers() const { return flags.isSet(HAS_SHARERS); }
5868833Sdam.sunwoo@arm.com    //@}
5874626SN/A
5884626SN/A    /**
5894626SN/A     * The express snoop flag is used for two purposes. Firstly, it is
5904626SN/A     * used to bypass flow control for normal (non-snoop) requests
5914626SN/A     * going downstream in the memory system. In cases where a cache
5928833Sdam.sunwoo@arm.com     * is responding to a snoop from another cache (it had a dirty
5934626SN/A     * line), but the line is not writable (and there are possibly
5944871SN/A     * other copies), the express snoop flag is set by the downstream
5954871SN/A     * cache to invalidate all other copies in zero time. Secondly,
5968833Sdam.sunwoo@arm.com     * the express snoop flag is also set to be able to distinguish
5978833Sdam.sunwoo@arm.com     * snoop packets that came from a downstream cache, rather than
5988833Sdam.sunwoo@arm.com     * snoop packets from neighbouring caches.
5994626SN/A     */
6004626SN/A    void setExpressSnoop()      { flags.set(EXPRESS_SNOOP); }
6014626SN/A    bool isExpressSnoop() const { return flags.isSet(EXPRESS_SNOOP); }
6024626SN/A
6034626SN/A    /**
6044626SN/A     * On responding to a snoop request (which only happens for
6054626SN/A     * Modified or Owned lines), make sure that we can transform an
6068833Sdam.sunwoo@arm.com     * Owned response to a Modified one. If this flag is not set, the
6074626SN/A     * responding cache had the line in the Owned state, and there are
6084626SN/A     * possibly other Shared copies in the memory system. A downstream
6094626SN/A     * cache helps in orchestrating the invalidation of these copies
6104626SN/A     * by sending out the appropriate express snoops.
6118833Sdam.sunwoo@arm.com     */
6128833Sdam.sunwoo@arm.com    void setResponderHadWritable()
6138833Sdam.sunwoo@arm.com    {
6144626SN/A        assert(cacheResponding());
6154626SN/A        assert(!responderHadWritable());
6164626SN/A        flags.set(RESPONDER_HAD_WRITABLE);
6174626SN/A    }
6184626SN/A    bool responderHadWritable() const
6198833Sdam.sunwoo@arm.com    { return flags.isSet(RESPONDER_HAD_WRITABLE); }
6204626SN/A
6214871SN/A    void setSuppressFuncError()     { flags.set(SUPPRESS_FUNC_ERROR); }
6224871SN/A    bool suppressFuncError() const  { return flags.isSet(SUPPRESS_FUNC_ERROR); }
6234871SN/A    void setBlockCached()          { flags.set(BLOCK_CACHED); }
6248833Sdam.sunwoo@arm.com    bool isBlockCached() const     { return flags.isSet(BLOCK_CACHED); }
6258833Sdam.sunwoo@arm.com    void clearBlockCached()        { flags.clear(BLOCK_CACHED); }
6268833Sdam.sunwoo@arm.com
6274626SN/A    // Network error conditions... encapsulate them as methods since
6284626SN/A    // their encoding keeps changing (from result field to command
6294626SN/A    // field, etc.)
6304626SN/A    void
6314626SN/A    setBadAddress()
6324626SN/A    {
6334626SN/A        assert(isResponse());
6344626SN/A        cmd = MemCmd::BadAddressError;
6354626SN/A    }
6364626SN/A
6374626SN/A    void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; }
6384626SN/A
6394626SN/A    Addr getAddr() const { assert(flags.isSet(VALID_ADDR)); return addr; }
6404626SN/A    /**
6414626SN/A     * Update the address of this packet mid-transaction. This is used
6424626SN/A     * by the address mapper to change an already set address to a new
6434626SN/A     * one based on the system configuration. It is intended to remap
6444626SN/A     * an existing address, so it asserts that the current address is
6454626SN/A     * valid.
6464626SN/A     */
6474626SN/A    void setAddr(Addr _addr) { assert(flags.isSet(VALID_ADDR)); addr = _addr; }
6484626SN/A
6494626SN/A    unsigned getSize() const  { assert(flags.isSet(VALID_SIZE)); return size; }
6504626SN/A
6514626SN/A    Addr getOffset(unsigned int blk_size) const
6524626SN/A    {
6534626SN/A        return getAddr() & Addr(blk_size - 1);
6544626SN/A    }
6554626SN/A
6564626SN/A    Addr getBlockAddr(unsigned int blk_size) const
6574626SN/A    {
6584626SN/A        return getAddr() & ~(Addr(blk_size - 1));
6594626SN/A    }
6604626SN/A
6614626SN/A    bool isSecure() const
6624626SN/A    {
6634626SN/A        assert(flags.isSet(VALID_ADDR));
6644626SN/A        return _isSecure;
6654626SN/A    }
6664626SN/A
6674626SN/A    /**
6684626SN/A     * Accessor function to atomic op.
6694626SN/A     */
6704626SN/A    AtomicOpFunctor *getAtomicOp() const { return req->getAtomicOpFunctor(); }
6714626SN/A    bool isAtomicOp() const { return req->isAtomic(); }
6728833Sdam.sunwoo@arm.com
6738833Sdam.sunwoo@arm.com    /**
6748833Sdam.sunwoo@arm.com     * It has been determined that the SC packet should successfully update
6758833Sdam.sunwoo@arm.com     * memory. Therefore, convert this SC packet to a normal write.
6764626SN/A     */
6774626SN/A    void
6784626SN/A    convertScToWrite()
6794626SN/A    {
6804626SN/A        assert(isLLSC());
6818833Sdam.sunwoo@arm.com        assert(isWrite());
6824626SN/A        cmd = MemCmd::WriteReq;
6834626SN/A    }
6848833Sdam.sunwoo@arm.com
6858833Sdam.sunwoo@arm.com    /**
6868833Sdam.sunwoo@arm.com     * When ruby is in use, Ruby will monitor the cache line and the
6874626SN/A     * phys memory should treat LL ops as normal reads.
6884626SN/A     */
6894626SN/A    void
6904626SN/A    convertLlToRead()
6918833Sdam.sunwoo@arm.com    {
6924626SN/A        assert(isLLSC());
6934626SN/A        assert(isRead());
6948833Sdam.sunwoo@arm.com        cmd = MemCmd::ReadReq;
6958833Sdam.sunwoo@arm.com    }
6968833Sdam.sunwoo@arm.com
6974626SN/A    /**
6984626SN/A     * Constructor. Note that a Request object must be constructed
6994626SN/A     * first, but the Requests's physical address and size fields need
7004626SN/A     * not be valid. The command must be supplied.
7014626SN/A     */
7024626SN/A    Packet(const RequestPtr _req, MemCmd _cmd)
7034626SN/A        :  cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false),
7044626SN/A           size(0), headerDelay(0), snoopDelay(0), payloadDelay(0),
7054626SN/A           senderState(NULL)
7064626SN/A    {
7074626SN/A        if (req->hasPaddr()) {
7084626SN/A            addr = req->getPaddr();
7094626SN/A            flags.set(VALID_ADDR);
7108833Sdam.sunwoo@arm.com            _isSecure = req->isSecure();
7118833Sdam.sunwoo@arm.com        }
7128833Sdam.sunwoo@arm.com        if (req->hasSize()) {
7138833Sdam.sunwoo@arm.com            size = req->getSize();
7144626SN/A            flags.set(VALID_SIZE);
7154626SN/A        }
7164626SN/A    }
7174626SN/A
7184626SN/A    /**
7198833Sdam.sunwoo@arm.com     * Alternate constructor if you are trying to create a packet with
7204626SN/A     * a request that is for a whole block, not the address from the
7214626SN/A     * req.  this allows for overriding the size/addr of the req.
7228833Sdam.sunwoo@arm.com     */
7238833Sdam.sunwoo@arm.com    Packet(const RequestPtr _req, MemCmd _cmd, int _blkSize)
7248833Sdam.sunwoo@arm.com        :  cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false),
7254626SN/A           headerDelay(0), snoopDelay(0), payloadDelay(0),
7264626SN/A           senderState(NULL)
7274626SN/A    {
7284626SN/A        if (req->hasPaddr()) {
7298833Sdam.sunwoo@arm.com            addr = req->getPaddr() & ~(_blkSize - 1);
7304626SN/A            flags.set(VALID_ADDR);
7314626SN/A            _isSecure = req->isSecure();
7328833Sdam.sunwoo@arm.com        }
7338833Sdam.sunwoo@arm.com        size = _blkSize;
7348833Sdam.sunwoo@arm.com        flags.set(VALID_SIZE);
7354626SN/A    }
7364626SN/A
7374626SN/A    /**
7384626SN/A     * Alternate constructor for copying a packet.  Copy all fields
7394626SN/A     * *except* if the original packet's data was dynamic, don't copy
7404626SN/A     * that, as we can't guarantee that the new packet's lifetime is
7414626SN/A     * less than that of the original packet.  In this case the new
7424626SN/A     * packet should allocate its own data.
7434626SN/A     */
7444626SN/A    Packet(const PacketPtr pkt, bool clear_flags, bool alloc_data)
7454626SN/A        :  cmd(pkt->cmd), req(pkt->req),
7464626SN/A           data(nullptr),
7474626SN/A           addr(pkt->addr), _isSecure(pkt->_isSecure), size(pkt->size),
7488833Sdam.sunwoo@arm.com           bytesValid(pkt->bytesValid),
7498833Sdam.sunwoo@arm.com           headerDelay(pkt->headerDelay),
7508833Sdam.sunwoo@arm.com           snoopDelay(0),
7518833Sdam.sunwoo@arm.com           payloadDelay(pkt->payloadDelay),
7524626SN/A           senderState(pkt->senderState)
7534626SN/A    {
7544626SN/A        if (!clear_flags)
7554626SN/A            flags.set(pkt->flags & COPY_FLAGS);
7564626SN/A
7578833Sdam.sunwoo@arm.com        flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE));
7584626SN/A
7594626SN/A        // should we allocate space for data, or not, the express
7608833Sdam.sunwoo@arm.com        // snoops do not need to carry any data as they only serve to
7618833Sdam.sunwoo@arm.com        // co-ordinate state changes
7628833Sdam.sunwoo@arm.com        if (alloc_data) {
7634626SN/A            // even if asked to allocate data, if the original packet
7644626SN/A            // holds static data, then the sender will not be doing
7658833Sdam.sunwoo@arm.com            // any memcpy on receiving the response, thus we simply
7664626SN/A            // carry the pointer forward
7674626SN/A            if (pkt->flags.isSet(STATIC_DATA)) {
7688833Sdam.sunwoo@arm.com                data = pkt->data;
7694626SN/A                flags.set(STATIC_DATA);
7708833Sdam.sunwoo@arm.com            } else {
7718833Sdam.sunwoo@arm.com                allocate();
7728833Sdam.sunwoo@arm.com            }
7734626SN/A        }
7744626SN/A    }
7754626SN/A
7768833Sdam.sunwoo@arm.com    /**
7774626SN/A     * Generate the appropriate read MemCmd based on the Request flags.
7784626SN/A     */
7798833Sdam.sunwoo@arm.com    static MemCmd
7804626SN/A    makeReadCmd(const RequestPtr req)
7818833Sdam.sunwoo@arm.com    {
7828833Sdam.sunwoo@arm.com        if (req->isLLSC())
7838833Sdam.sunwoo@arm.com            return MemCmd::LoadLockedReq;
7844626SN/A        else if (req->isPrefetch())
7854626SN/A            return MemCmd::SoftPFReq;
7864626SN/A        else
7874626SN/A            return MemCmd::ReadReq;
7884626SN/A    }
7894626SN/A
7902810SN/A    /**
791     * Generate the appropriate write MemCmd based on the Request flags.
792     */
793    static MemCmd
794    makeWriteCmd(const RequestPtr req)
795    {
796        if (req->isLLSC())
797            return MemCmd::StoreCondReq;
798        else if (req->isSwap())
799            return MemCmd::SwapReq;
800        else
801            return MemCmd::WriteReq;
802    }
803
804    /**
805     * Constructor-like methods that return Packets based on Request objects.
806     * Fine-tune the MemCmd type if it's not a vanilla read or write.
807     */
808    static PacketPtr
809    createRead(const RequestPtr req)
810    {
811        return new Packet(req, makeReadCmd(req));
812    }
813
814    static PacketPtr
815    createWrite(const RequestPtr req)
816    {
817        return new Packet(req, makeWriteCmd(req));
818    }
819
820    /**
821     * clean up packet variables
822     */
823    ~Packet()
824    {
825        // Delete the request object if this is a request packet which
826        // does not need a response, because the requester will not get
827        // a chance. If the request packet needs a response then the
828        // request will be deleted on receipt of the response
829        // packet. We also make sure to never delete the request for
830        // express snoops, even for cases when responses are not
831        // needed (CleanEvict and Writeback), since the snoop packet
832        // re-uses the same request.
833        if (req && isRequest() && !needsResponse() &&
834            !isExpressSnoop()) {
835            delete req;
836        }
837        deleteData();
838    }
839
840    /**
841     * Take a request packet and modify it in place to be suitable for
842     * returning as a response to that request.
843     */
844    void
845    makeResponse()
846    {
847        assert(needsResponse());
848        assert(isRequest());
849        cmd = cmd.responseCommand();
850
851        // responses are never express, even if the snoop that
852        // triggered them was
853        flags.clear(EXPRESS_SNOOP);
854    }
855
856    void
857    makeAtomicResponse()
858    {
859        makeResponse();
860    }
861
862    void
863    makeTimingResponse()
864    {
865        makeResponse();
866    }
867
868    void
869    setFunctionalResponseStatus(bool success)
870    {
871        if (!success) {
872            if (isWrite()) {
873                cmd = MemCmd::FunctionalWriteError;
874            } else {
875                cmd = MemCmd::FunctionalReadError;
876            }
877        }
878    }
879
880    void
881    setSize(unsigned size)
882    {
883        assert(!flags.isSet(VALID_SIZE));
884
885        this->size = size;
886        flags.set(VALID_SIZE);
887    }
888
889
890  public:
891    /**
892     * @{
893     * @name Data accessor mehtods
894     */
895
896    /**
897     * Set the data pointer to the following value that should not be
898     * freed. Static data allows us to do a single memcpy even if
899     * multiple packets are required to get from source to destination
900     * and back. In essence the pointer is set calling dataStatic on
901     * the original packet, and whenever this packet is copied and
902     * forwarded the same pointer is passed on. When a packet
903     * eventually reaches the destination holding the data, it is
904     * copied once into the location originally set. On the way back
905     * to the source, no copies are necessary.
906     */
907    template <typename T>
908    void
909    dataStatic(T *p)
910    {
911        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
912        data = (PacketDataPtr)p;
913        flags.set(STATIC_DATA);
914    }
915
916    /**
917     * Set the data pointer to the following value that should not be
918     * freed. This version of the function allows the pointer passed
919     * to us to be const. To avoid issues down the line we cast the
920     * constness away, the alternative would be to keep both a const
921     * and non-const data pointer and cleverly choose between
922     * them. Note that this is only allowed for static data.
923     */
924    template <typename T>
925    void
926    dataStaticConst(const T *p)
927    {
928        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
929        data = const_cast<PacketDataPtr>(p);
930        flags.set(STATIC_DATA);
931    }
932
933    /**
934     * Set the data pointer to a value that should have delete []
935     * called on it. Dynamic data is local to this packet, and as the
936     * packet travels from source to destination, forwarded packets
937     * will allocate their own data. When a packet reaches the final
938     * destination it will populate the dynamic data of that specific
939     * packet, and on the way back towards the source, memcpy will be
940     * invoked in every step where a new packet was created e.g. in
941     * the caches. Ultimately when the response reaches the source a
942     * final memcpy is needed to extract the data from the packet
943     * before it is deallocated.
944     */
945    template <typename T>
946    void
947    dataDynamic(T *p)
948    {
949        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
950        data = (PacketDataPtr)p;
951        flags.set(DYNAMIC_DATA);
952    }
953
954    /**
955     * get a pointer to the data ptr.
956     */
957    template <typename T>
958    T*
959    getPtr()
960    {
961        assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
962        return (T*)data;
963    }
964
965    template <typename T>
966    const T*
967    getConstPtr() const
968    {
969        assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
970        return (const T*)data;
971    }
972
973    /**
974     * Get the data in the packet byte swapped from big endian to
975     * host endian.
976     */
977    template <typename T>
978    T getBE() const;
979
980    /**
981     * Get the data in the packet byte swapped from little endian to
982     * host endian.
983     */
984    template <typename T>
985    T getLE() const;
986
987    /**
988     * Get the data in the packet byte swapped from the specified
989     * endianness.
990     */
991    template <typename T>
992    T get(ByteOrder endian) const;
993
994    /**
995     * Get the data in the packet byte swapped from guest to host
996     * endian.
997     */
998    template <typename T>
999    T get() const;
1000
1001    /** Set the value in the data pointer to v as big endian. */
1002    template <typename T>
1003    void setBE(T v);
1004
1005    /** Set the value in the data pointer to v as little endian. */
1006    template <typename T>
1007    void setLE(T v);
1008
1009    /**
1010     * Set the value in the data pointer to v using the specified
1011     * endianness.
1012     */
1013    template <typename T>
1014    void set(T v, ByteOrder endian);
1015
1016    /** Set the value in the data pointer to v as guest endian. */
1017    template <typename T>
1018    void set(T v);
1019
1020    /**
1021     * Copy data into the packet from the provided pointer.
1022     */
1023    void
1024    setData(const uint8_t *p)
1025    {
1026        // we should never be copying data onto itself, which means we
1027        // must idenfity packets with static data, as they carry the
1028        // same pointer from source to destination and back
1029        assert(p != getPtr<uint8_t>() || flags.isSet(STATIC_DATA));
1030
1031        if (p != getPtr<uint8_t>())
1032            // for packet with allocated dynamic data, we copy data from
1033            // one to the other, e.g. a forwarded response to a response
1034            std::memcpy(getPtr<uint8_t>(), p, getSize());
1035    }
1036
1037    /**
1038     * Copy data into the packet from the provided block pointer,
1039     * which is aligned to the given block size.
1040     */
1041    void
1042    setDataFromBlock(const uint8_t *blk_data, int blkSize)
1043    {
1044        setData(blk_data + getOffset(blkSize));
1045    }
1046
1047    /**
1048     * Copy data from the packet to the provided block pointer, which
1049     * is aligned to the given block size.
1050     */
1051    void
1052    writeData(uint8_t *p) const
1053    {
1054        std::memcpy(p, getConstPtr<uint8_t>(), getSize());
1055    }
1056
1057    /**
1058     * Copy data from the packet to the memory at the provided pointer.
1059     */
1060    void
1061    writeDataToBlock(uint8_t *blk_data, int blkSize) const
1062    {
1063        writeData(blk_data + getOffset(blkSize));
1064    }
1065
1066    /**
1067     * delete the data pointed to in the data pointer. Ok to call to
1068     * matter how data was allocted.
1069     */
1070    void
1071    deleteData()
1072    {
1073        if (flags.isSet(DYNAMIC_DATA))
1074            delete [] data;
1075
1076        flags.clear(STATIC_DATA|DYNAMIC_DATA);
1077        data = NULL;
1078    }
1079
1080    /** Allocate memory for the packet. */
1081    void
1082    allocate()
1083    {
1084        // if either this command or the response command has a data
1085        // payload, actually allocate space
1086        if (hasData() || hasRespData()) {
1087            assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
1088            flags.set(DYNAMIC_DATA);
1089            data = new uint8_t[getSize()];
1090        }
1091    }
1092
1093    /** @} */
1094
1095  private: // Private data accessor methods
1096    /** Get the data in the packet without byte swapping. */
1097    template <typename T>
1098    T getRaw() const;
1099
1100    /** Set the value in the data pointer to v without byte swapping. */
1101    template <typename T>
1102    void setRaw(T v);
1103
1104  public:
1105    /**
1106     * Check a functional request against a memory value stored in
1107     * another packet (i.e. an in-transit request or
1108     * response). Returns true if the current packet is a read, and
1109     * the other packet provides the data, which is then copied to the
1110     * current packet. If the current packet is a write, and the other
1111     * packet intersects this one, then we update the data
1112     * accordingly.
1113     */
1114    bool
1115    checkFunctional(PacketPtr other)
1116    {
1117        // all packets that are carrying a payload should have a valid
1118        // data pointer
1119        return checkFunctional(other, other->getAddr(), other->isSecure(),
1120                               other->getSize(),
1121                               other->hasData() ?
1122                               other->getPtr<uint8_t>() : NULL);
1123    }
1124
1125    /**
1126     * Does the request need to check for cached copies of the same block
1127     * in the memory hierarchy above.
1128     **/
1129    bool
1130    mustCheckAbove() const
1131    {
1132        return cmd == MemCmd::HardPFReq || isEviction();
1133    }
1134
1135    /**
1136     * Is this packet a clean eviction, including both actual clean
1137     * evict packets, but also clean writebacks.
1138     */
1139    bool
1140    isCleanEviction() const
1141    {
1142        return cmd == MemCmd::CleanEvict || cmd == MemCmd::WritebackClean;
1143    }
1144
1145    /**
1146     * Check a functional request against a memory value represented
1147     * by a base/size pair and an associated data array. If the
1148     * current packet is a read, it may be satisfied by the memory
1149     * value. If the current packet is a write, it may update the
1150     * memory value.
1151     */
1152    bool
1153    checkFunctional(Printable *obj, Addr base, bool is_secure, int size,
1154                    uint8_t *_data);
1155
1156    /**
1157     * Push label for PrintReq (safe to call unconditionally).
1158     */
1159    void
1160    pushLabel(const std::string &lbl)
1161    {
1162        if (isPrint())
1163            safe_cast<PrintReqState*>(senderState)->pushLabel(lbl);
1164    }
1165
1166    /**
1167     * Pop label for PrintReq (safe to call unconditionally).
1168     */
1169    void
1170    popLabel()
1171    {
1172        if (isPrint())
1173            safe_cast<PrintReqState*>(senderState)->popLabel();
1174    }
1175
1176    void print(std::ostream &o, int verbosity = 0,
1177               const std::string &prefix = "") const;
1178
1179    /**
1180     * A no-args wrapper of print(std::ostream...)
1181     * meant to be invoked from DPRINTFs
1182     * avoiding string overheads in fast mode
1183     * @return string with the request's type and start<->end addresses
1184     */
1185    std::string print() const;
1186};
1187
1188#endif //__MEM_PACKET_HH
1189