packet.hh revision 13860
11689SN/A/*
22316SN/A * Copyright (c) 2012-2019 ARM Limited
31689SN/A * All rights reserved
41689SN/A *
51689SN/A * The license below extends only to copyright in the software and shall
61689SN/A * not be construed as granting a license to any other intellectual
71689SN/A * property including but not limited to intellectual property relating
81689SN/A * to a hardware implementation of the functionality of the software
91689SN/A * licensed hereunder.  You may use the software subject to the license
101689SN/A * terms below provided that you ensure that this notice is replicated
111689SN/A * unmodified and in its entirety in all distributions of the software,
121689SN/A * modified or unmodified, in source code or in binary form.
131689SN/A *
141689SN/A * Copyright (c) 2006 The Regents of The University of Michigan
151689SN/A * Copyright (c) 2010,2015 Advanced Micro Devices, Inc.
161689SN/A * All rights reserved.
171689SN/A *
181689SN/A * Redistribution and use in source and binary forms, with or without
191689SN/A * modification, are permitted provided that the following conditions are
201689SN/A * met: redistributions of source code must retain the above copyright
211689SN/A * notice, this list of conditions and the following disclaimer;
221689SN/A * redistributions in binary form must reproduce the above copyright
231689SN/A * notice, this list of conditions and the following disclaimer in the
241689SN/A * documentation and/or other materials provided with the distribution;
251689SN/A * neither the name of the copyright holders nor the names of its
261689SN/A * contributors may be used to endorse or promote products derived from
272665Ssaidi@eecs.umich.edu * this software without specific prior written permission.
282665Ssaidi@eecs.umich.edu *
292965Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
301689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
311689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
322292SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
332329SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
342292SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
353577Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
365953Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
372292SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
381060SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
396221Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
406658Snate@binkert.org *
416221Snate@binkert.org * Authors: Ron Dreslinski
422292SN/A *          Steve Reinhardt
431717SN/A *          Ali Saidi
442292SN/A *          Andreas Hansson
456221Snate@binkert.org *          Nikos Nikoleris
462292SN/A */
472790Sktlim@umich.edu
482790Sktlim@umich.edu/**
492790Sktlim@umich.edu * @file
502790Sktlim@umich.edu * Declaration of the Packet class.
516221Snate@binkert.org */
525529Snate@binkert.org
531061SN/A#ifndef __MEM_PACKET_HH__
542292SN/A#define __MEM_PACKET_HH__
556221Snate@binkert.org
565606Snate@binkert.org#include <bitset>
571060SN/A#include <cassert>
585769Snate@binkert.org#include <list>
591060SN/A
601060SN/A#include "base/addr_range.hh"
611061SN/A#include "base/cast.hh"
621060SN/A#include "base/compiler.hh"
632292SN/A#include "base/flags.hh"
641062SN/A#include "base/logging.hh"
652316SN/A#include "base/printable.hh"
662316SN/A#include "base/types.hh"
672292SN/A#include "config/the_isa.hh"
682292SN/A#include "mem/request.hh"
692292SN/A#include "sim/core.hh"
702292SN/A
712292SN/Aclass Packet;
725336Shines@cs.fsu.edutypedef Packet *PacketPtr;
732292SN/Atypedef uint8_t* PacketDataPtr;
744873Sstever@eecs.umich.edutypedef std::list<PacketPtr> PacketList;
752292SN/Atypedef uint64_t PacketId;
762292SN/A
772292SN/Aclass MemCmd
785529Snate@binkert.org{
794329Sktlim@umich.edu    friend class Packet;
804329Sktlim@umich.edu
812292SN/A  public:
822292SN/A    /**
832292SN/A     * List of all commands associated with a packet.
842292SN/A     */
852292SN/A    enum Command
862292SN/A    {
875529Snate@binkert.org        InvalidCmd,
882843Sktlim@umich.edu        ReadReq,
892316SN/A        ReadResp,
902874Sktlim@umich.edu        ReadRespWithInvalidate,
912292SN/A        WriteReq,
922292SN/A        WriteResp,
932292SN/A        WritebackDirty,
942980Sgblack@eecs.umich.edu        WritebackClean,
952292SN/A        WriteClean,            // writes dirty data below without evicting
962292SN/A        CleanEvict,
972292SN/A        SoftPFReq,
982292SN/A        SoftPFExReq,
992292SN/A        HardPFReq,
1002292SN/A        SoftPFResp,
1012292SN/A        HardPFResp,
1022292SN/A        WriteLineReq,
1032292SN/A        UpgradeReq,
1044329Sktlim@umich.edu        SCUpgradeReq,           // Special "weak" upgrade for StoreCond
1052292SN/A        UpgradeResp,
1062292SN/A        SCUpgradeFailReq,       // Failed SCUpgradeReq in MSHR (never sent)
1072292SN/A        UpgradeFailResp,        // Valid for SCUpgradeReq only
1082292SN/A        ReadExReq,
1096221Snate@binkert.org        ReadExResp,
1102292SN/A        ReadCleanReq,
1112292SN/A        ReadSharedReq,
1122292SN/A        LoadLockedReq,
1134329Sktlim@umich.edu        StoreCondReq,
1142292SN/A        StoreCondFailReq,       // Failed StoreCondReq in MSHR (never sent)
1152292SN/A        StoreCondResp,
1162292SN/A        SwapReq,
1174329Sktlim@umich.edu        SwapResp,
1182292SN/A        MessageReq,
1192292SN/A        MessageResp,
1202292SN/A        MemFenceReq,
1212292SN/A        MemFenceResp,
1222292SN/A        CleanSharedReq,
1236221Snate@binkert.org        CleanSharedResp,
1246221Snate@binkert.org        CleanInvalidReq,
1256221Snate@binkert.org        CleanInvalidResp,
1266221Snate@binkert.org        // Error responses
1276221Snate@binkert.org        // @TODO these should be classified as responses rather than
1286221Snate@binkert.org        // requests; coding them as requests initially for backwards
1296221Snate@binkert.org        // compatibility
1306221Snate@binkert.org        InvalidDestError,  // packet dest field invalid
1317720Sgblack@eecs.umich.edu        BadAddressError,   // memory address invalid
1322292SN/A        FunctionalReadError, // unable to fulfill functional read
1333640Sktlim@umich.edu        FunctionalWriteError, // unable to fulfill functional write
1343640Sktlim@umich.edu        // Fake simulator-only commands
1353640Sktlim@umich.edu        PrintReq,       // Print state matching address
1362292SN/A        FlushReq,      //request for a cache flush
1372292SN/A        InvalidateReq,   // request for address to be invalidated
1382292SN/A        InvalidateResp,
1392292SN/A        NUM_MEM_CMDS
1402292SN/A    };
1412292SN/A
1422292SN/A  private:
1432292SN/A    /**
1442292SN/A     * List of command attributes.
1452292SN/A     */
1462292SN/A    enum Attribute
1472292SN/A    {
1482132SN/A        IsRead,         //!< Data flows from responder to requester
1492301SN/A        IsWrite,        //!< Data flows from requester to responder
1501062SN/A        IsUpgrade,
1511062SN/A        IsInvalidate,
1521062SN/A        IsClean,        //!< Cleans any existing dirty blocks
1531062SN/A        NeedsWritable,  //!< Requires writable copy to complete in-cache
1541062SN/A        IsRequest,      //!< Issued by requester
1551062SN/A        IsResponse,     //!< Issue by responder
1561062SN/A        NeedsResponse,  //!< Requester needs response from target
1571062SN/A        IsEviction,
1581062SN/A        IsSWPrefetch,
1591062SN/A        IsHWPrefetch,
1601062SN/A        IsLlsc,         //!< Alpha/MIPS LL or SC access
1611062SN/A        HasData,        //!< There is an associated payload
1621062SN/A        IsError,        //!< Error response
1631062SN/A        IsPrint,        //!< Print state matching address (for debugging)
1641062SN/A        IsFlush,        //!< Flush the address from caches
1651062SN/A        FromCache,      //!< Request originated from a caching agent
1661062SN/A        NUM_COMMAND_ATTRIBUTES
1671062SN/A    };
1681062SN/A
1691062SN/A    /**
1701062SN/A     * Structure that defines attributes and other data associated
1712292SN/A     * with a Command.
1721062SN/A     */
1731062SN/A    struct CommandInfo
1741062SN/A    {
1751062SN/A        /// Set of attribute flags.
1761062SN/A        const std::bitset<NUM_COMMAND_ATTRIBUTES> attributes;
1772301SN/A        /// Corresponding response for requests; InvalidCmd if no
1782316SN/A        /// response is applicable.
1796221Snate@binkert.org        const Command response;
1802301SN/A        /// String representation (for printing)
1812301SN/A        const std::string str;
1822301SN/A    };
1832301SN/A
1842301SN/A    /// Array to map Command enum to associated info.
1852316SN/A    static const CommandInfo commandInfo[];
1866221Snate@binkert.org
1872301SN/A  private:
1882301SN/A
1892301SN/A    Command cmd;
1902301SN/A
1912301SN/A    bool
1922316SN/A    testCmdAttrib(MemCmd::Attribute attrib) const
1936221Snate@binkert.org    {
1942301SN/A        return commandInfo[cmd].attributes[attrib] != 0;
1952301SN/A    }
1962301SN/A
1972301SN/A  public:
1982301SN/A
1992316SN/A    bool isRead() const            { return testCmdAttrib(IsRead); }
2006221Snate@binkert.org    bool isWrite() const           { return testCmdAttrib(IsWrite); }
2012301SN/A    bool isUpgrade() const         { return testCmdAttrib(IsUpgrade); }
2022301SN/A    bool isRequest() const         { return testCmdAttrib(IsRequest); }
2032301SN/A    bool isResponse() const        { return testCmdAttrib(IsResponse); }
2042301SN/A    bool needsWritable() const     { return testCmdAttrib(NeedsWritable); }
2052301SN/A    bool needsResponse() const     { return testCmdAttrib(NeedsResponse); }
2062316SN/A    bool isInvalidate() const      { return testCmdAttrib(IsInvalidate); }
2076221Snate@binkert.org    bool isEviction() const        { return testCmdAttrib(IsEviction); }
2082301SN/A    bool isClean() const           { return testCmdAttrib(IsClean); }
2092301SN/A    bool fromCache() const         { return testCmdAttrib(FromCache); }
2102301SN/A
2112301SN/A    /**
2122301SN/A     * A writeback is an eviction that carries data.
2132316SN/A     */
2146221Snate@binkert.org    bool isWriteback() const       { return testCmdAttrib(IsEviction) &&
2152301SN/A                                            testCmdAttrib(HasData); }
2162301SN/A
2172301SN/A    /**
2182301SN/A     * Check if this particular packet type carries payload data. Note
2192301SN/A     * that this does not reflect if the data pointer of the packet is
2202316SN/A     * valid or not.
2216221Snate@binkert.org     */
2222301SN/A    bool hasData() const        { return testCmdAttrib(HasData); }
2232301SN/A    bool isLLSC() const         { return testCmdAttrib(IsLlsc); }
2242301SN/A    bool isSWPrefetch() const   { return testCmdAttrib(IsSWPrefetch); }
2252301SN/A    bool isHWPrefetch() const   { return testCmdAttrib(IsHWPrefetch); }
2262301SN/A    bool isPrefetch() const     { return testCmdAttrib(IsSWPrefetch) ||
2272316SN/A                                         testCmdAttrib(IsHWPrefetch); }
2282301SN/A    bool isError() const        { return testCmdAttrib(IsError); }
2292301SN/A    bool isPrint() const        { return testCmdAttrib(IsPrint); }
2302301SN/A    bool isFlush() const        { return testCmdAttrib(IsFlush); }
2311062SN/A
2321062SN/A    Command
2331062SN/A    responseCommand() const
2341062SN/A    {
2352980Sgblack@eecs.umich.edu        return commandInfo[cmd].response;
2362292SN/A    }
2372292SN/A
2382292SN/A    /// Return the string to a cmd given by idx.
2392292SN/A    const std::string &toString() const { return commandInfo[cmd].str; }
2402292SN/A    int toInt() const { return (int)cmd; }
2412292SN/A
2422292SN/A    MemCmd(Command _cmd) : cmd(_cmd) { }
2431060SN/A    MemCmd(int _cmd) : cmd((Command)_cmd) { }
2441060SN/A    MemCmd() : cmd(InvalidCmd) { }
2451060SN/A
2461060SN/A    bool operator==(MemCmd c2) const { return (cmd == c2.cmd); }
2471060SN/A    bool operator!=(MemCmd c2) const { return (cmd != c2.cmd); }
2481060SN/A};
2491060SN/A
2501060SN/A/**
2511060SN/A * A Packet is used to encapsulate a transfer between two objects in
2521060SN/A * the memory system (e.g., the L1 and L2 cache).  (In contrast, a
2531061SN/A * single Request travels all the way from the requester to the
2541060SN/A * ultimate destination and back, possibly being conveyed by several
2552292SN/A * different Packets along the way.)
2562292SN/A */
2572292SN/Aclass Packet : public Printable
2582292SN/A{
2592292SN/A  public:
2602292SN/A    typedef uint32_t FlagsType;
2612292SN/A    typedef ::Flags<FlagsType> Flags;
2622292SN/A
2632292SN/A  private:
2642292SN/A
2652292SN/A    enum : FlagsType {
2661060SN/A        // Flags to transfer across when copying a packet
2671060SN/A        COPY_FLAGS             = 0x0000003F,
2681060SN/A
2691060SN/A        // Flags that are used to create reponse packets
2701060SN/A        RESPONDER_FLAGS        = 0x00000009,
2711060SN/A
2721060SN/A        // Does this packet have sharers (which means it should not be
2731061SN/A        // considered writable) or not. See setHasSharers below.
2741060SN/A        HAS_SHARERS            = 0x00000001,
2752292SN/A
2761060SN/A        // Special control flags
2771060SN/A        /// Special timing-mode atomic snoop for multi-level coherence.
2781060SN/A        EXPRESS_SNOOP          = 0x00000002,
2791060SN/A
2801060SN/A        /// Allow a responding cache to inform the cache hierarchy
2811060SN/A        /// that it had a writable copy before responding. See
2821060SN/A        /// setResponderHadWritable below.
2831061SN/A        RESPONDER_HAD_WRITABLE = 0x00000004,
2841060SN/A
2852292SN/A        // Snoop co-ordination flag to indicate that a cache is
2862292SN/A        // responding to a snoop. See setCacheResponding below.
2872292SN/A        CACHE_RESPONDING       = 0x00000008,
2882292SN/A
2892292SN/A        // The writeback/writeclean should be propagated further
2902292SN/A        // downstream by the receiver
2912292SN/A        WRITE_THROUGH          = 0x00000010,
2926221Snate@binkert.org
2932292SN/A        // Response co-ordination flag for cache maintenance
2942292SN/A        // operations
2952292SN/A        SATISFIED              = 0x00000020,
2962292SN/A
2972292SN/A        /// Are the 'addr' and 'size' fields valid?
2982292SN/A        VALID_ADDR             = 0x00000100,
2992292SN/A        VALID_SIZE             = 0x00000200,
3002292SN/A
3016221Snate@binkert.org        /// Is the data pointer set to a value that shouldn't be freed
3026221Snate@binkert.org        /// when the packet is destroyed?
3032292SN/A        STATIC_DATA            = 0x00001000,
3042292SN/A        /// The data pointer points to a value that should be freed when
3052292SN/A        /// the packet is destroyed. The pointer is assumed to be pointing
3062292SN/A        /// to an array, and delete [] is consequently called
3072292SN/A        DYNAMIC_DATA           = 0x00002000,
3081060SN/A
3091060SN/A        /// suppress the error if this packet encounters a functional
3101060SN/A        /// access failure.
3111060SN/A        SUPPRESS_FUNC_ERROR    = 0x00008000,
3121061SN/A
3131060SN/A        // Signal block present to squash prefetch and cache evict packets
3142292SN/A        // through express snoop flag
3151060SN/A        BLOCK_CACHED          = 0x00010000
3162292SN/A    };
3172292SN/A
3181060SN/A    Flags flags;
3192292SN/A
3206221Snate@binkert.org  public:
3216221Snate@binkert.org    typedef MemCmd::Command Command;
3226221Snate@binkert.org
3236221Snate@binkert.org    /// The command field of the packet.
3241060SN/A    MemCmd cmd;
3251060SN/A
3264329Sktlim@umich.edu    const PacketId id;
3274329Sktlim@umich.edu
3284329Sktlim@umich.edu    /// A pointer to the original request.
3294329Sktlim@umich.edu    RequestPtr req;
3302292SN/A
3315100Ssaidi@eecs.umich.edu  private:
3321060SN/A   /**
3331060SN/A    * A pointer to the data being transferred. It can be different
3341061SN/A    * sizes at each level of the hierarchy so it belongs to the
3352863Sktlim@umich.edu    * packet, not request. This may or may not be populated when a
3362843Sktlim@umich.edu    * responder receives the packet. If not populated memory should
3371060SN/A    * be allocated.
3382843Sktlim@umich.edu    */
3392863Sktlim@umich.edu    PacketDataPtr data;
3402863Sktlim@umich.edu
3412316SN/A    /// The address of the request.  This address could be virtual or
3422316SN/A    /// physical, depending on the system configuration.
3432316SN/A    Addr addr;
3442316SN/A
3452843Sktlim@umich.edu    /// True if the request targets the secure memory space.
3462316SN/A    bool _isSecure;
3472316SN/A
3482843Sktlim@umich.edu    /// The size of the request or transfer.
3492307SN/A    unsigned size;
3502307SN/A
3512307SN/A    /**
3522307SN/A     * Track the bytes found that satisfy a functional read.
3532307SN/A     */
3542843Sktlim@umich.edu    std::vector<bool> bytesValid;
3552843Sktlim@umich.edu
3562864Sktlim@umich.edu    // Quality of Service priority value
3572843Sktlim@umich.edu    uint8_t _qosValue;
3582843Sktlim@umich.edu
3592843Sktlim@umich.edu  public:
3602843Sktlim@umich.edu
3612307SN/A    /**
3622307SN/A     * The extra delay from seeing the packet until the header is
3632316SN/A     * transmitted. This delay is used to communicate the crossbar
3642307SN/A     * forwarding latency to the neighbouring object (e.g. a cache)
3652307SN/A     * that actually makes the packet wait. As the delay is relative,
3666221Snate@binkert.org     * a 32-bit unsigned should be sufficient.
3676221Snate@binkert.org     */
3686221Snate@binkert.org    uint32_t headerDelay;
3696221Snate@binkert.org
3706221Snate@binkert.org    /**
3712307SN/A     * Keep track of the extra delay incurred by snooping upwards
3722307SN/A     * before sending a request down the memory system. This is used
3732307SN/A     * by the coherent crossbar to account for the additional request
3742307SN/A     * delay.
3752307SN/A     */
3762307SN/A    uint32_t snoopDelay;
3772307SN/A
3782292SN/A    /**
3792132SN/A     * The extra pipelining delay from seeing the packet until the end of
3802316SN/A     * payload is transmitted by the component that provided it (if
3816221Snate@binkert.org     * any). This includes the header delay. Similar to the header
3826221Snate@binkert.org     * delay, this is used to make up for the fact that the
3833867Sbinkertn@umich.edu     * crossbar does not make the packet wait. As the delay is
3843867Sbinkertn@umich.edu     * relative, a 32-bit unsigned should be sufficient.
3856221Snate@binkert.org     */
3863867Sbinkertn@umich.edu    uint32_t payloadDelay;
3872316SN/A
3882316SN/A    /**
3892316SN/A     * A virtual base opaque structure used to hold state associated
3902316SN/A     * with the packet (e.g., an MSHR), specific to a MemObject that
3912316SN/A     * sees the packet. A pointer to this state is returned in the
3922316SN/A     * packet's response so that the MemObject in question can quickly
3932316SN/A     * look up the state needed to process it. A specific subclass
3942292SN/A     * would be derived from this to carry state specific to a
3952292SN/A     * particular sending device.
3962292SN/A     *
3972292SN/A     * As multiple MemObjects may add their SenderState throughout the
3982733Sktlim@umich.edu     * memory system, the SenderStates create a stack, where a
3992292SN/A     * MemObject can add a new Senderstate, as long as the
4002292SN/A     * predecessing SenderState is restored when the response comes
4012733Sktlim@umich.edu     * back. For this reason, the predecessor should always be
4022292SN/A     * populated with the current SenderState of a packet before
4032292SN/A     * modifying the senderState field in the request packet.
4042292SN/A     */
4052292SN/A    struct SenderState
4062292SN/A    {
4072292SN/A        SenderState* predecessor;
4082292SN/A        SenderState() : predecessor(NULL) {}
4092292SN/A        virtual ~SenderState() {}
4102292SN/A    };
4112292SN/A
4122292SN/A    /**
4136221Snate@binkert.org     * Object used to maintain state of a PrintReq.  The senderState
4146221Snate@binkert.org     * field of a PrintReq should always be of this type.
4152292SN/A     */
4163867Sbinkertn@umich.edu    class PrintReqState : public SenderState
4176221Snate@binkert.org    {
4182292SN/A      private:
4192292SN/A        /**
4202292SN/A         * An entry in the label stack.
4212292SN/A         */
4222292SN/A        struct LabelStackEntry
4232292SN/A        {
4242702Sktlim@umich.edu            const std::string label;
4252292SN/A            std::string *prefix;
4262292SN/A            bool labelPrinted;
4272292SN/A            LabelStackEntry(const std::string &_label, std::string *_prefix);
4282292SN/A        };
4292292SN/A
4302292SN/A        typedef std::list<LabelStackEntry> LabelStack;
4312292SN/A        LabelStack labelStack;
4322292SN/A
4332292SN/A        std::string *curPrefixPtr;
4342292SN/A
4352292SN/A      public:
4362292SN/A        std::ostream &os;
4376221Snate@binkert.org        const int verbosity;
4386221Snate@binkert.org
4392292SN/A        PrintReqState(std::ostream &os, int verbosity = 0);
4403867Sbinkertn@umich.edu        ~PrintReqState();
4416221Snate@binkert.org
4422292SN/A        /**
4432292SN/A         * Returns the current line prefix.
4442292SN/A         */
4452292SN/A        const std::string &curPrefix() { return *curPrefixPtr; }
4462292SN/A
4472292SN/A        /**
4482292SN/A         * Push a label onto the label stack, and prepend the given
4492292SN/A         * prefix string onto the current prefix.  Labels will only be
4502292SN/A         * printed if an object within the label's scope is printed.
4512292SN/A         */
4526221Snate@binkert.org        void pushLabel(const std::string &lbl,
4536221Snate@binkert.org                       const std::string &prefix = "  ");
4542292SN/A
4552292SN/A        /**
4562292SN/A         * Pop a label off the label stack.
4572292SN/A         */
4582292SN/A        void popLabel();
4592292SN/A
4606221Snate@binkert.org        /**
4612292SN/A         * Print all of the pending unprinted labels on the
4622292SN/A         * stack. Called by printObj(), so normally not called by
4632292SN/A         * users unless bypassing printObj().
4642292SN/A         */
4652292SN/A        void printLabels();
4665606Snate@binkert.org
4674035Sktlim@umich.edu        /**
4682292SN/A         * Print a Printable object to os, because it matched the
4692292SN/A         * address on a PrintReq.
4702292SN/A         */
4712292SN/A        void printObj(Printable *obj);
4726221Snate@binkert.org    };
4732292SN/A
4744035Sktlim@umich.edu    /**
4752680Sktlim@umich.edu     * This packet's sender state.  Devices should use dynamic_cast<>
4762292SN/A     * to cast to the state appropriate to the sender.  The intent of
4772680Sktlim@umich.edu     * this variable is to allow a device to attach extra information
4782292SN/A     * to a request. A response packet must return the sender state
4792292SN/A     * that was attached to the original request (even if a new packet
4802292SN/A     * is created).
4812292SN/A     */
4826221Snate@binkert.org    SenderState *senderState;
4832292SN/A
4842292SN/A    /**
4852292SN/A     * Push a new sender state to the packet and make the current
4862292SN/A     * sender state the predecessor of the new one. This should be
4872292SN/A     * prefered over direct manipulation of the senderState member
4882292SN/A     * variable.
4894035Sktlim@umich.edu     *
4902292SN/A     * @param sender_state SenderState to push at the top of the stack
4912292SN/A     */
4922292SN/A    void pushSenderState(SenderState *sender_state);
4932292SN/A
4942292SN/A    /**
4952292SN/A     * Pop the top of the state stack and return a pointer to it. This
4962292SN/A     * assumes the current sender state is not NULL. This should be
4972292SN/A     * preferred over direct manipulation of the senderState member
4982292SN/A     * variable.
4992292SN/A     *
5002292SN/A     * @return The current top of the stack
5012292SN/A     */
5022292SN/A    SenderState *popSenderState();
5032292SN/A
5042292SN/A    /**
5052292SN/A     * Go through the sender state stack and return the first instance
5062292SN/A     * that is of type T (as determined by a dynamic_cast). If there
5072292SN/A     * is no sender state of type T, NULL is returned.
5082292SN/A     *
5092292SN/A     * @return The topmost state of type T
5102292SN/A     */
5112292SN/A    template <typename T>
5127720Sgblack@eecs.umich.edu    T * findNextSenderState() const
5132316SN/A    {
5142292SN/A        T *t = NULL;
5152316SN/A        SenderState* sender_state = senderState;
5162316SN/A        while (t == NULL && sender_state != NULL) {
5176221Snate@binkert.org            t = dynamic_cast<T*>(sender_state);
5182316SN/A            sender_state = sender_state->predecessor;
5192316SN/A        }
5202316SN/A        return t;
5217720Sgblack@eecs.umich.edu    }
5222316SN/A
5232316SN/A    /// Return the string name of the cmd field (for debugging and
5242316SN/A    /// tracing).
5254035Sktlim@umich.edu    const std::string &cmdString() const { return cmd.toString(); }
5262316SN/A
5272316SN/A    /// Return the index of this command.
5282316SN/A    inline int cmdToIndex() const { return cmd.toInt(); }
5292316SN/A
5302316SN/A    bool isRead() const              { return cmd.isRead(); }
5312316SN/A    bool isWrite() const             { return cmd.isWrite(); }
5322316SN/A    bool isUpgrade()  const          { return cmd.isUpgrade(); }
5332316SN/A    bool isRequest() const           { return cmd.isRequest(); }
5342316SN/A    bool isResponse() const          { return cmd.isResponse(); }
5356221Snate@binkert.org    bool needsWritable() const
5362316SN/A    {
5372316SN/A        // we should never check if a response needsWritable, the
5382292SN/A        // request has this flag, and for a response we should rather
5397720Sgblack@eecs.umich.edu        // look at the hasSharers flag (if not set, the response is to
5402292SN/A        // be considered writable)
5412292SN/A        assert(isRequest());
5422292SN/A        return cmd.needsWritable();
5432316SN/A    }
5442292SN/A    bool needsResponse() const       { return cmd.needsResponse(); }
5452292SN/A    bool isInvalidate() const        { return cmd.isInvalidate(); }
5462292SN/A    bool isEviction() const          { return cmd.isEviction(); }
5472680Sktlim@umich.edu    bool isClean() const             { return cmd.isClean(); }
5482292SN/A    bool fromCache() const           { return cmd.fromCache(); }
5492292SN/A    bool isWriteback() const         { return cmd.isWriteback(); }
5502292SN/A    bool hasData() const             { return cmd.hasData(); }
5512292SN/A    bool hasRespData() const
5522292SN/A    {
5532292SN/A        MemCmd resp_cmd = cmd.responseCommand();
5542292SN/A        return resp_cmd.hasData();
5552292SN/A    }
5562292SN/A    bool isLLSC() const              { return cmd.isLLSC(); }
5572843Sktlim@umich.edu    bool isError() const             { return cmd.isError(); }
5582843Sktlim@umich.edu    bool isPrint() const             { return cmd.isPrint(); }
5592843Sktlim@umich.edu    bool isFlush() const             { return cmd.isFlush(); }
5602316SN/A
5612316SN/A    bool isWholeLineWrite(unsigned blk_size)
5622316SN/A    {
5633867Sbinkertn@umich.edu        return (cmd == MemCmd::WriteReq || cmd == MemCmd::WriteLineReq) &&
5642875Sksewell@umich.edu            getOffset(blk_size) == 0 && getSize() == blk_size;
5652875Sksewell@umich.edu    }
5666221Snate@binkert.org
5676221Snate@binkert.org    //@{
5682292SN/A    /// Snoop flags
5692316SN/A    /**
5702316SN/A     * Set the cacheResponding flag. This is used by the caches to
5713867Sbinkertn@umich.edu     * signal another cache that they are responding to a request. A
5726221Snate@binkert.org     * cache will only respond to snoops if it has the line in either
5732292SN/A     * Modified or Owned state. Note that on snoop hits we always pass
5744035Sktlim@umich.edu     * the line as Modified and never Owned. In the case of an Owned
5754035Sktlim@umich.edu     * line we proceed to invalidate all other copies.
5764035Sktlim@umich.edu     *
5774035Sktlim@umich.edu     * On a cache fill (see Cache::handleFill), we check hasSharers
5782292SN/A     * first, ignoring the cacheResponding flag if hasSharers is set.
5792292SN/A     * A line is consequently allocated as:
5802292SN/A     *
5812292SN/A     * hasSharers cacheResponding state
5822292SN/A     * true       false           Shared
5832292SN/A     * true       true            Shared
5842877Sksewell@umich.edu     * false      false           Exclusive
5852702Sktlim@umich.edu     * false      true            Modified
5862702Sktlim@umich.edu     */
5872702Sktlim@umich.edu    void setCacheResponding()
5882292SN/A    {
5892292SN/A        assert(isRequest());
5902292SN/A        assert(!flags.isSet(CACHE_RESPONDING));
5912292SN/A        flags.set(CACHE_RESPONDING);
5922292SN/A    }
5932292SN/A    bool cacheResponding() const { return flags.isSet(CACHE_RESPONDING); }
5942292SN/A    /**
5952292SN/A     * On fills, the hasSharers flag is used by the caches in
5963867Sbinkertn@umich.edu     * combination with the cacheResponding flag, as clarified
5972292SN/A     * above. If the hasSharers flag is not set, the packet is passing
5983867Sbinkertn@umich.edu     * writable. Thus, a response from a memory passes the line as
5996221Snate@binkert.org     * writable by default.
6002292SN/A     *
6012292SN/A     * The hasSharers flag is also used by upstream caches to inform a
6022292SN/A     * downstream cache that they have the block (by calling
6032292SN/A     * setHasSharers on snoop request packets that hit in upstream
6042292SN/A     * cachs tags or MSHRs). If the snoop packet has sharers, a
6052292SN/A     * downstream cache is prevented from passing a dirty line upwards
6062292SN/A     * if it was not explicitly asked for a writable copy. See
6072292SN/A     * Cache::satisfyCpuSideRequest.
6087720Sgblack@eecs.umich.edu     *
6092292SN/A     * The hasSharers flag is also used on writebacks, in
6107720Sgblack@eecs.umich.edu     * combination with the WritbackClean or WritebackDirty commands,
6112292SN/A     * to allocate the block downstream either as:
6122292SN/A     *
6132292SN/A     * command        hasSharers state
6142292SN/A     * WritebackDirty false      Modified
6152292SN/A     * WritebackDirty true       Owned
6167720Sgblack@eecs.umich.edu     * WritebackClean false      Exclusive
6177720Sgblack@eecs.umich.edu     * WritebackClean true       Shared
6182292SN/A     */
6192292SN/A    void setHasSharers()    { flags.set(HAS_SHARERS); }
6202292SN/A    bool hasSharers() const { return flags.isSet(HAS_SHARERS); }
6212292SN/A    //@}
6222292SN/A
6232292SN/A    /**
6242292SN/A     * The express snoop flag is used for two purposes. Firstly, it is
6252292SN/A     * used to bypass flow control for normal (non-snoop) requests
6262316SN/A     * going downstream in the memory system. In cases where a cache
6272292SN/A     * is responding to a snoop from another cache (it had a dirty
6282292SN/A     * line), but the line is not writable (and there are possibly
6292292SN/A     * other copies), the express snoop flag is set by the downstream
6302292SN/A     * cache to invalidate all other copies in zero time. Secondly,
6312292SN/A     * the express snoop flag is also set to be able to distinguish
6322292SN/A     * snoop packets that came from a downstream cache, rather than
6334035Sktlim@umich.edu     * snoop packets from neighbouring caches.
6342292SN/A     */
6352292SN/A    void setExpressSnoop()      { flags.set(EXPRESS_SNOOP); }
6364035Sktlim@umich.edu    bool isExpressSnoop() const { return flags.isSet(EXPRESS_SNOOP); }
6372292SN/A
6383640Sktlim@umich.edu    /**
6392316SN/A     * On responding to a snoop request (which only happens for
6402316SN/A     * Modified or Owned lines), make sure that we can transform an
6412292SN/A     * Owned response to a Modified one. If this flag is not set, the
6423633Sktlim@umich.edu     * responding cache had the line in the Owned state, and there are
6433633Sktlim@umich.edu     * possibly other Shared copies in the memory system. A downstream
6443633Sktlim@umich.edu     * cache helps in orchestrating the invalidation of these copies
6453633Sktlim@umich.edu     * by sending out the appropriate express snoops.
6464035Sktlim@umich.edu     */
6474035Sktlim@umich.edu    void setResponderHadWritable()
6484035Sktlim@umich.edu    {
6492292SN/A        assert(cacheResponding());
6502292SN/A        assert(!responderHadWritable());
6512292SN/A        flags.set(RESPONDER_HAD_WRITABLE);
6523633Sktlim@umich.edu    }
6533640Sktlim@umich.edu    bool responderHadWritable() const
6542292SN/A    { return flags.isSet(RESPONDER_HAD_WRITABLE); }
6553633Sktlim@umich.edu
6563633Sktlim@umich.edu    /**
6572292SN/A     * Copy the reponse flags from an input packet to this packet. The
6582292SN/A     * reponse flags determine whether a responder has been found and
6592292SN/A     * the state at which the block will be at the destination.
6602292SN/A     *
6612292SN/A     * @pkt The packet that we will copy flags from
6623640Sktlim@umich.edu     */
6632292SN/A    void copyResponderFlags(const PacketPtr pkt);
6642292SN/A
6652292SN/A    /**
6664035Sktlim@umich.edu     * A writeback/writeclean cmd gets propagated further downstream
6675704Snate@binkert.org     * by the receiver when the flag is set.
6684035Sktlim@umich.edu     */
6694035Sktlim@umich.edu    void setWriteThrough()
6703640Sktlim@umich.edu    {
6713640Sktlim@umich.edu        assert(cmd.isWrite() &&
6723640Sktlim@umich.edu               (cmd.isEviction() || cmd == MemCmd::WriteClean));
6733640Sktlim@umich.edu        flags.set(WRITE_THROUGH);
6743640Sktlim@umich.edu    }
6753640Sktlim@umich.edu    void clearWriteThrough() { flags.clear(WRITE_THROUGH); }
6763640Sktlim@umich.edu    bool writeThrough() const { return flags.isSet(WRITE_THROUGH); }
6773640Sktlim@umich.edu
6783640Sktlim@umich.edu    /**
6793640Sktlim@umich.edu     * Set when a request hits in a cache and the cache is not going
6803640Sktlim@umich.edu     * to respond. This is used by the crossbar to coordinate
6813640Sktlim@umich.edu     * responses for cache maintenance operations.
6823640Sktlim@umich.edu     */
6833640Sktlim@umich.edu    void setSatisfied()
6841060SN/A    {
6854035Sktlim@umich.edu        assert(cmd.isClean());
6864035Sktlim@umich.edu        assert(!flags.isSet(SATISFIED));
6873634Sktlim@umich.edu        flags.set(SATISFIED);
6884035Sktlim@umich.edu    }
6894035Sktlim@umich.edu    bool satisfied() const { return flags.isSet(SATISFIED); }
6904035Sktlim@umich.edu
6914035Sktlim@umich.edu    void setSuppressFuncError()     { flags.set(SUPPRESS_FUNC_ERROR); }
6924035Sktlim@umich.edu    bool suppressFuncError() const  { return flags.isSet(SUPPRESS_FUNC_ERROR); }
6934035Sktlim@umich.edu    void setBlockCached()          { flags.set(BLOCK_CACHED); }
6944035Sktlim@umich.edu    bool isBlockCached() const     { return flags.isSet(BLOCK_CACHED); }
6954035Sktlim@umich.edu    void clearBlockCached()        { flags.clear(BLOCK_CACHED); }
6964035Sktlim@umich.edu
6975704Snate@binkert.org    /**
6984035Sktlim@umich.edu     * QoS Value getter
6994035Sktlim@umich.edu     * Returns 0 if QoS value was never set (constructor default).
7001060SN/A     *
7011060SN/A     * @return QoS priority value of the packet
7021060SN/A     */
7032316SN/A    inline uint8_t qosValue() const { return _qosValue; }
7041060SN/A
7056221Snate@binkert.org    /**
7066221Snate@binkert.org     * QoS Value setter
7071060SN/A     * Interface for setting QoS priority value of the packet.
7083867Sbinkertn@umich.edu     *
7096221Snate@binkert.org     * @param qos_value QoS priority value
7101060SN/A     */
7112292SN/A    inline void qosValue(const uint8_t qos_value)
7122292SN/A    { _qosValue = qos_value; }
7132292SN/A
7142680Sktlim@umich.edu    inline MasterID masterId() const { return req->masterId(); }
7152292SN/A
7162680Sktlim@umich.edu    // Network error conditions... encapsulate them as methods since
7174035Sktlim@umich.edu    // their encoding keeps changing (from result field to command
7182680Sktlim@umich.edu    // field, etc.)
7192292SN/A    void
7201061SN/A    setBadAddress()
7212292SN/A    {
7222292SN/A        assert(isResponse());
7232292SN/A        cmd = MemCmd::BadAddressError;
7242292SN/A    }
7252292SN/A
7262292SN/A    void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; }
7271061SN/A
7282292SN/A    Addr getAddr() const { assert(flags.isSet(VALID_ADDR)); return addr; }
7292292SN/A    /**
7302292SN/A     * Update the address of this packet mid-transaction. This is used
7312292SN/A     * by the address mapper to change an already set address to a new
7321061SN/A     * one based on the system configuration. It is intended to remap
7332292SN/A     * an existing address, so it asserts that the current address is
7342292SN/A     * valid.
7357720Sgblack@eecs.umich.edu     */
7361061SN/A    void setAddr(Addr _addr) { assert(flags.isSet(VALID_ADDR)); addr = _addr; }
7372292SN/A
7381061SN/A    unsigned getSize() const  { assert(flags.isSet(VALID_SIZE)); return size; }
7392292SN/A
7402292SN/A    /**
7412292SN/A     * Get address range to which this packet belongs.
7421062SN/A     *
7432935Sksewell@umich.edu     * @return Address range of this packet.
7442292SN/A     */
7452935Sksewell@umich.edu    AddrRange getAddrRange() const;
7464035Sktlim@umich.edu
7472292SN/A    Addr getOffset(unsigned int blk_size) const
7482292SN/A    {
7492292SN/A        return getAddr() & Addr(blk_size - 1);
7502292SN/A    }
7513093Sksewell@umich.edu
7522292SN/A    Addr getBlockAddr(unsigned int blk_size) const
7532292SN/A    {
7542292SN/A        return getAddr() & ~(Addr(blk_size - 1));
7552292SN/A    }
7562292SN/A
7572292SN/A    bool isSecure() const
7582292SN/A    {
7592292SN/A        assert(flags.isSet(VALID_ADDR));
7602292SN/A        return _isSecure;
7612292SN/A    }
7622292SN/A
7632292SN/A    /**
7642292SN/A     * Accessor function to atomic op.
7652292SN/A     */
7662292SN/A    AtomicOpFunctor *getAtomicOp() const { return req->getAtomicOpFunctor(); }
7672292SN/A    bool isAtomicOp() const { return req->isAtomic(); }
7687720Sgblack@eecs.umich.edu
7692292SN/A    /**
7702316SN/A     * It has been determined that the SC packet should successfully update
7712292SN/A     * memory. Therefore, convert this SC packet to a normal write.
7722292SN/A     */
7732292SN/A    void
7742292SN/A    convertScToWrite()
7751062SN/A    {
7762292SN/A        assert(isLLSC());
7771060SN/A        assert(isWrite());
7781060SN/A        cmd = MemCmd::WriteReq;
7792292SN/A    }
7802292SN/A
7812292SN/A    /**
7821061SN/A     * When ruby is in use, Ruby will monitor the cache line and the
7831060SN/A     * phys memory should treat LL ops as normal reads.
7841060SN/A     */
7851061SN/A    void
7861060SN/A    convertLlToRead()
7871060SN/A    {
7881060SN/A        assert(isLLSC());
7892292SN/A        assert(isRead());
7903867Sbinkertn@umich.edu        cmd = MemCmd::ReadReq;
7912292SN/A    }
7923867Sbinkertn@umich.edu
7936221Snate@binkert.org    /**
7942292SN/A     * Constructor. Note that a Request object must be constructed
7952292SN/A     * first, but the Requests's physical address and size fields need
7962292SN/A     * not be valid. The command must be supplied.
7972292SN/A     */
7982292SN/A    Packet(const RequestPtr &_req, MemCmd _cmd)
7992292SN/A        :  cmd(_cmd), id((PacketId)_req.get()), req(_req),
8002292SN/A           data(nullptr), addr(0), _isSecure(false), size(0),
8014035Sktlim@umich.edu           _qosValue(0), headerDelay(0), snoopDelay(0),
8024035Sktlim@umich.edu           payloadDelay(0), senderState(NULL)
8032292SN/A    {
8044035Sktlim@umich.edu        if (req->hasPaddr()) {
8054035Sktlim@umich.edu            addr = req->getPaddr();
8064035Sktlim@umich.edu            flags.set(VALID_ADDR);
8074035Sktlim@umich.edu            _isSecure = req->isSecure();
8084035Sktlim@umich.edu        }
8094035Sktlim@umich.edu        if (req->hasSize()) {
8104035Sktlim@umich.edu            size = req->getSize();
8114035Sktlim@umich.edu            flags.set(VALID_SIZE);
8124035Sktlim@umich.edu        }
8134035Sktlim@umich.edu    }
8145557Sktlim@umich.edu
8154035Sktlim@umich.edu    /**
8164035Sktlim@umich.edu     * Alternate constructor if you are trying to create a packet with
8174035Sktlim@umich.edu     * a request that is for a whole block, not the address from the
8184035Sktlim@umich.edu     * req.  this allows for overriding the size/addr of the req.
8194035Sktlim@umich.edu     */
8204035Sktlim@umich.edu    Packet(const RequestPtr &_req, MemCmd _cmd, int _blkSize, PacketId _id = 0)
8214035Sktlim@umich.edu        :  cmd(_cmd), id(_id ? _id : (PacketId)_req.get()), req(_req),
8221060SN/A           data(nullptr), addr(0), _isSecure(false),
8231060SN/A           _qosValue(0), headerDelay(0),
8241060SN/A           snoopDelay(0), payloadDelay(0), senderState(NULL)
8251061SN/A    {
8261060SN/A        if (req->hasPaddr()) {
8272292SN/A            addr = req->getPaddr() & ~(_blkSize - 1);
8281060SN/A            flags.set(VALID_ADDR);
8291060SN/A            _isSecure = req->isSecure();
8301060SN/A        }
8312316SN/A        size = _blkSize;
8322316SN/A        flags.set(VALID_SIZE);
8332316SN/A    }
8342316SN/A
8352316SN/A    /**
8361060SN/A     * Alternate constructor for copying a packet.  Copy all fields
8371060SN/A     * *except* if the original packet's data was dynamic, don't copy
8382292SN/A     * that, as we can't guarantee that the new packet's lifetime is
8391060SN/A     * less than that of the original packet.  In this case the new
8401060SN/A     * packet should allocate its own data.
8411060SN/A     */
8422292SN/A    Packet(const PacketPtr pkt, bool clear_flags, bool alloc_data)
8432316SN/A        :  cmd(pkt->cmd), id(pkt->id), req(pkt->req),
8441060SN/A           data(nullptr),
8451060SN/A           addr(pkt->addr), _isSecure(pkt->_isSecure), size(pkt->size),
8462292SN/A           bytesValid(pkt->bytesValid),
8472292SN/A           _qosValue(pkt->qosValue()),
8481060SN/A           headerDelay(pkt->headerDelay),
8492292SN/A           snoopDelay(0),
8502292SN/A           payloadDelay(pkt->payloadDelay),
8512292SN/A           senderState(pkt->senderState)
8522292SN/A    {
8532292SN/A        if (!clear_flags)
8546221Snate@binkert.org            flags.set(pkt->flags & COPY_FLAGS);
8552292SN/A
8562292SN/A        flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE));
8572292SN/A
8582292SN/A        // should we allocate space for data, or not, the express
8592292SN/A        // snoops do not need to carry any data as they only serve to
8602132SN/A        // co-ordinate state changes
8612316SN/A        if (alloc_data) {
8622316SN/A            // even if asked to allocate data, if the original packet
8631060SN/A            // holds static data, then the sender will not be doing
8641060SN/A            // any memcpy on receiving the response, thus we simply
8652292SN/A            // carry the pointer forward
8661060SN/A            if (pkt->flags.isSet(STATIC_DATA)) {
8671060SN/A                data = pkt->data;
8682292SN/A                flags.set(STATIC_DATA);
8691060SN/A            } else {
8701062SN/A                allocate();
8711062SN/A            }
8722292SN/A        }
8732292SN/A    }
8741060SN/A
8757720Sgblack@eecs.umich.edu    /**
8762292SN/A     * Generate the appropriate read MemCmd based on the Request flags.
8771060SN/A     */
8781060SN/A    static MemCmd
8791060SN/A    makeReadCmd(const RequestPtr &req)
8801061SN/A    {
8811061SN/A        if (req->isLLSC())
8822292SN/A            return MemCmd::LoadLockedReq;
8831060SN/A        else if (req->isPrefetchEx())
8841060SN/A            return MemCmd::SoftPFExReq;
8851060SN/A        else if (req->isPrefetch())
8861060SN/A            return MemCmd::SoftPFReq;
8871062SN/A        else
8881060SN/A            return MemCmd::ReadReq;
8891060SN/A    }
8902292SN/A
8912292SN/A    /**
8922292SN/A     * Generate the appropriate write MemCmd based on the Request flags.
8932292SN/A     */
8941060SN/A    static MemCmd
8951062SN/A    makeWriteCmd(const RequestPtr &req)
8961062SN/A    {
8972292SN/A        if (req->isLLSC())
8982292SN/A            return MemCmd::StoreCondReq;
8992292SN/A        else if (req->isSwap() || req->isAtomic())
9002292SN/A            return MemCmd::SwapReq;
9011062SN/A        else if (req->isCacheInvalidate()) {
9022292SN/A          return req->isCacheClean() ? MemCmd::CleanInvalidReq :
9037720Sgblack@eecs.umich.edu              MemCmd::InvalidateReq;
9042935Sksewell@umich.edu        } else if (req->isCacheClean()) {
9052292SN/A            return MemCmd::CleanSharedReq;
9062292SN/A        } else
9075108Sgblack@eecs.umich.edu            return MemCmd::WriteReq;
9085108Sgblack@eecs.umich.edu    }
9095108Sgblack@eecs.umich.edu
9102292SN/A    /**
9117720Sgblack@eecs.umich.edu     * Constructor-like methods that return Packets based on Request objects.
9125108Sgblack@eecs.umich.edu     * Fine-tune the MemCmd type if it's not a vanilla read or write.
9132292SN/A     */
9147720Sgblack@eecs.umich.edu    static PacketPtr
9152292SN/A    createRead(const RequestPtr &req)
9165108Sgblack@eecs.umich.edu    {
9175108Sgblack@eecs.umich.edu        return new Packet(req, makeReadCmd(req));
9182292SN/A    }
9192292SN/A
9201060SN/A    static PacketPtr
9217720Sgblack@eecs.umich.edu    createWrite(const RequestPtr &req)
9222292SN/A    {
9237720Sgblack@eecs.umich.edu        return new Packet(req, makeWriteCmd(req));
9241060SN/A    }
9251060SN/A
9261060SN/A    /**
9271060SN/A     * clean up packet variables
9281062SN/A     */
9291063SN/A    ~Packet()
9302292SN/A    {
9312307SN/A        deleteData();
9322307SN/A    }
9332349SN/A
9342307SN/A    /**
9351060SN/A     * Take a request packet and modify it in place to be suitable for
9361060SN/A     * returning as a response to that request.
9371061SN/A     */
9381060SN/A    void
9392292SN/A    makeResponse()
9401060SN/A    {
9411060SN/A        assert(needsResponse());
9421060SN/A        assert(isRequest());
9436221Snate@binkert.org        cmd = cmd.responseCommand();
9442292SN/A
9452316SN/A        // responses are never express, even if the snoop that
9462316SN/A        // triggered them was
9471061SN/A        flags.clear(EXPRESS_SNOOP);
9481061SN/A    }
9491061SN/A
9502292SN/A    void
9511062SN/A    makeAtomicResponse()
9522292SN/A    {
9532348SN/A        makeResponse();
9542292SN/A    }
9552292SN/A
9562316SN/A    void
9572316SN/A    makeTimingResponse()
9587720Sgblack@eecs.umich.edu    {
9597720Sgblack@eecs.umich.edu        makeResponse();
9602316SN/A    }
9615557Sktlim@umich.edu
9622292SN/A    void
9632292SN/A    setFunctionalResponseStatus(bool success)
9642292SN/A    {
9652292SN/A        if (!success) {
9662292SN/A            if (isWrite()) {
9671061SN/A                cmd = MemCmd::FunctionalWriteError;
9681061SN/A            } else {
9691061SN/A                cmd = MemCmd::FunctionalReadError;
9701061SN/A            }
9711061SN/A        }
9721062SN/A    }
9731062SN/A
9741061SN/A    void
9752292SN/A    setSize(unsigned size)
9765557Sktlim@umich.edu    {
9774035Sktlim@umich.edu        assert(!flags.isSet(VALID_SIZE));
9784035Sktlim@umich.edu
9794035Sktlim@umich.edu        this->size = size;
9804035Sktlim@umich.edu        flags.set(VALID_SIZE);
9814035Sktlim@umich.edu    }
9827720Sgblack@eecs.umich.edu
9837720Sgblack@eecs.umich.edu    /**
9842292SN/A     * Check if packet corresponds to a given block-aligned address and
9852292SN/A     * address space.
9862316SN/A     *
9872292SN/A     * @param addr The address to compare against.
9882292SN/A     * @param is_secure Whether addr belongs to the secure address space.
9892292SN/A     * @param blk_size Block size in bytes.
9902292SN/A     * @return Whether packet matches description.
9912292SN/A     */
9922292SN/A    bool matchBlockAddr(const Addr addr, const bool is_secure,
9932292SN/A                        const int blk_size) const;
9941061SN/A
9952292SN/A    /**
9961061SN/A     * Check if this packet refers to the same block-aligned address and
9971061SN/A     * address space as another packet.
9981060SN/A     *
9991060SN/A     * @param pkt The packet to compare against.
10002316SN/A     * @param blk_size Block size in bytes.
10012292SN/A     * @return Whether packet matches description.
10022316SN/A     */
10032132SN/A    bool matchBlockAddr(const PacketPtr pkt, const int blk_size) const;
10042132SN/A
10054035Sktlim@umich.edu    /**
10064035Sktlim@umich.edu     * Check if packet corresponds to a given address and address space.
10074035Sktlim@umich.edu     *
10082316SN/A     * @param addr The address to compare against.
10094035Sktlim@umich.edu     * @param is_secure Whether addr belongs to the secure address space.
10102310SN/A     * @return Whether packet matches description.
10112310SN/A     */
10122310SN/A    bool matchAddr(const Addr addr, const bool is_secure) const;
10132733Sktlim@umich.edu
10142316SN/A    /**
10152316SN/A     * Check if this packet refers to the same address and address space as
10162316SN/A     * another packet.
10172732Sktlim@umich.edu     *
10181060SN/A     * @param pkt The packet to compare against.
10192733Sktlim@umich.edu     * @return Whether packet matches description.
10201060SN/A     */
10212112SN/A    bool matchAddr(const PacketPtr pkt) const;
10227720Sgblack@eecs.umich.edu
10237720Sgblack@eecs.umich.edu  public:
10242292SN/A    /**
10255557Sktlim@umich.edu     * @{
10262316SN/A     * @name Data accessor mehtods
10272316SN/A     */
10282316SN/A
10292310SN/A    /**
10304035Sktlim@umich.edu     * Set the data pointer to the following value that should not be
10314035Sktlim@umich.edu     * freed. Static data allows us to do a single memcpy even if
10322733Sktlim@umich.edu     * multiple packets are required to get from source to destination
10332316SN/A     * and back. In essence the pointer is set calling dataStatic on
10342732Sktlim@umich.edu     * the original packet, and whenever this packet is copied and
10352316SN/A     * forwarded the same pointer is passed on. When a packet
10362733Sktlim@umich.edu     * eventually reaches the destination holding the data, it is
10372292SN/A     * copied once into the location originally set. On the way back
10382316SN/A     * to the source, no copies are necessary.
10392292SN/A     */
10402316SN/A    template <typename T>
10412316SN/A    void
10422316SN/A    dataStatic(T *p)
10432292SN/A    {
10442316SN/A        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
10452316SN/A        data = (PacketDataPtr)p;
10462316SN/A        flags.set(STATIC_DATA);
10472316SN/A    }
10482316SN/A
10492316SN/A    /**
10507684Sgblack@eecs.umich.edu     * Set the data pointer to the following value that should not be
10512292SN/A     * freed. This version of the function allows the pointer passed
10522316SN/A     * to us to be const. To avoid issues down the line we cast the
10532316SN/A     * constness away, the alternative would be to keep both a const
10542292SN/A     * and non-const data pointer and cleverly choose between
10552316SN/A     * them. Note that this is only allowed for static data.
10562292SN/A     */
10574035Sktlim@umich.edu    template <typename T>
10586667Ssteve.reinhardt@amd.com    void
10596667Ssteve.reinhardt@amd.com    dataStaticConst(const T *p)
10606667Ssteve.reinhardt@amd.com    {
10616667Ssteve.reinhardt@amd.com        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
10626667Ssteve.reinhardt@amd.com        data = const_cast<PacketDataPtr>(p);
10634288Sktlim@umich.edu        flags.set(STATIC_DATA);
10644035Sktlim@umich.edu    }
10654035Sktlim@umich.edu
10664035Sktlim@umich.edu    /**
10672316SN/A     * Set the data pointer to a value that should have delete []
10682316SN/A     * called on it. Dynamic data is local to this packet, and as the
10692316SN/A     * packet travels from source to destination, forwarded packets
10701060SN/A     * will allocate their own data. When a packet reaches the final
10711060SN/A     * destination it will populate the dynamic data of that specific
10722301SN/A     * packet, and on the way back towards the source, memcpy will be
10732132SN/A     * invoked in every step where a new packet was created e.g. in
10742362SN/A     * the caches. Ultimately when the response reaches the source a
10752362SN/A     * final memcpy is needed to extract the data from the packet
10767720Sgblack@eecs.umich.edu     * before it is deallocated.
10773126Sktlim@umich.edu     */
10782362SN/A    template <typename T>
10792362SN/A    void
10802362SN/A    dataDynamic(T *p)
10812362SN/A    {
10822362SN/A        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
10835953Ssaidi@eecs.umich.edu        data = (PacketDataPtr)p;
10845953Ssaidi@eecs.umich.edu        flags.set(DYNAMIC_DATA);
10855953Ssaidi@eecs.umich.edu    }
10867720Sgblack@eecs.umich.edu
10875953Ssaidi@eecs.umich.edu    /**
10885953Ssaidi@eecs.umich.edu     * get a pointer to the data ptr.
10892362SN/A     */
10902362SN/A    template <typename T>
10912132SN/A    T*
10922292SN/A    getPtr()
10932292SN/A    {
10944046Sbinkertn@umich.edu        assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
10954046Sbinkertn@umich.edu        return (T*)data;
10962292SN/A    }
10971060SN/A
10981060SN/A    template <typename T>
10992292SN/A    const T*
11002292SN/A    getConstPtr() const
11013771Sgblack@eecs.umich.edu    {
11022292SN/A        assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
11031060SN/A        return (const T*)data;
11041062SN/A    }
11052353SN/A
11062353SN/A    /**
11072353SN/A     * Get the data in the packet byte swapped from big endian to
11082292SN/A     * host endian.
11092292SN/A     */
11101060SN/A    template <typename T>
11114035Sktlim@umich.edu    T getBE() const;
11124035Sktlim@umich.edu
11134035Sktlim@umich.edu    /**
11144035Sktlim@umich.edu     * Get the data in the packet byte swapped from little endian to
11151060SN/A     * host endian.
11161060SN/A     */
11171060SN/A    template <typename T>
11181060SN/A    T getLE() const;
11191061SN/A
11201060SN/A    /**
11212292SN/A     * Get the data in the packet byte swapped from the specified
11221060SN/A     * endianness.
11232935Sksewell@umich.edu     */
11242935Sksewell@umich.edu    template <typename T>
11253093Sksewell@umich.edu    T get(ByteOrder endian) const;
11263093Sksewell@umich.edu
11272965Sksewell@umich.edu#if THE_ISA != NULL_ISA
11282965Sksewell@umich.edu    /**
11292965Sksewell@umich.edu     * Get the data in the packet byte swapped from guest to host
11302965Sksewell@umich.edu     * endian.
11313093Sksewell@umich.edu     */
11326221Snate@binkert.org    template <typename T>
11332292SN/A    T get() const
11342292SN/A        M5_DEPRECATED_MSG("The memory system should be ISA independent.");
11354035Sktlim@umich.edu#endif
11364035Sktlim@umich.edu
11372292SN/A    /** Set the value in the data pointer to v as big endian. */
11382292SN/A    template <typename T>
11397720Sgblack@eecs.umich.edu    void setBE(T v);
11407720Sgblack@eecs.umich.edu
11412292SN/A    /** Set the value in the data pointer to v as little endian. */
11422292SN/A    template <typename T>
11432292SN/A    void setLE(T v);
11442292SN/A
11452292SN/A    /**
11462292SN/A     * Set the value in the data pointer to v using the specified
11471061SN/A     * endianness.
11487720Sgblack@eecs.umich.edu     */
11491061SN/A    template <typename T>
11507720Sgblack@eecs.umich.edu    void set(T v, ByteOrder endian);
11511061SN/A
11521060SN/A#if THE_ISA != NULL_ISA
11532965Sksewell@umich.edu    /** Set the value in the data pointer to v as guest endian. */
11542965Sksewell@umich.edu    template <typename T>
11552965Sksewell@umich.edu    void set(T v)
11562965Sksewell@umich.edu        M5_DEPRECATED_MSG("The memory system should be ISA independent.");
11572965Sksewell@umich.edu#endif
11582965Sksewell@umich.edu
11592965Sksewell@umich.edu    /**
11602965Sksewell@umich.edu     * Get the data in the packet byte swapped from the specified
11612965Sksewell@umich.edu     * endianness and zero-extended to 64 bits.
11622965Sksewell@umich.edu     */
11632965Sksewell@umich.edu    uint64_t getUintX(ByteOrder endian) const;
11642965Sksewell@umich.edu
11652965Sksewell@umich.edu    /**
11667720Sgblack@eecs.umich.edu     * Set the value in the word w after truncating it to the length
11677720Sgblack@eecs.umich.edu     * of the packet and then byteswapping it to the desired
11683221Sktlim@umich.edu     * endianness.
11692965Sksewell@umich.edu     */
11702965Sksewell@umich.edu    void setUintX(uint64_t w, ByteOrder endian);
11717720Sgblack@eecs.umich.edu
11722965Sksewell@umich.edu    /**
11737720Sgblack@eecs.umich.edu     * Copy data into the packet from the provided pointer.
11742965Sksewell@umich.edu     */
11752965Sksewell@umich.edu    void
11761060SN/A    setData(const uint8_t *p)
11771060SN/A    {
11781061SN/A        // we should never be copying data onto itself, which means we
11791060SN/A        // must idenfity packets with static data, as they carry the
11802292SN/A        // same pointer from source to destination and back
11811060SN/A        assert(p != getPtr<uint8_t>() || flags.isSet(STATIC_DATA));
11821060SN/A
11831060SN/A        if (p != getPtr<uint8_t>())
11841060SN/A            // for packet with allocated dynamic data, we copy data from
11851681SN/A            // one to the other, e.g. a forwarded response to a response
11861060SN/A            std::memcpy(getPtr<uint8_t>(), p, getSize());
11871060SN/A    }
11882292SN/A
11897720Sgblack@eecs.umich.edu    /**
11902316SN/A     * Copy data into the packet from the provided block pointer,
11912292SN/A     * which is aligned to the given block size.
11927720Sgblack@eecs.umich.edu     */
11932292SN/A    void
11941060SN/A    setDataFromBlock(const uint8_t *blk_data, int blkSize)
11952292SN/A    {
11962292SN/A        setData(blk_data + getOffset(blkSize));
11972292SN/A    }
11981060SN/A
11991060SN/A    /**
12001060SN/A     * Copy data from the packet to the memory at the provided pointer.
12011061SN/A     * @param p Pointer to which data will be copied.
12022292SN/A     */
12032292SN/A    void
12041060SN/A    writeData(uint8_t *p) const
12056221Snate@binkert.org    {
12066221Snate@binkert.org        std::memcpy(p, getConstPtr<uint8_t>(), getSize());
12072292SN/A    }
12083867Sbinkertn@umich.edu
12096221Snate@binkert.org    /**
12102292SN/A     * Copy data from the packet to the provided block pointer, which
12112292SN/A     * is aligned to the given block size.
12122292SN/A     * @param blk_data Pointer to block to which data will be copied.
12132292SN/A     * @param blkSize Block size in bytes.
12142292SN/A     */
12152292SN/A    void
12161060SN/A    writeDataToBlock(uint8_t *blk_data, int blkSize) const
12172292SN/A    {
12182301SN/A        writeData(blk_data + getOffset(blkSize));
12192301SN/A    }
12202301SN/A
12212301SN/A    /**
12226221Snate@binkert.org     * delete the data pointed to in the data pointer. Ok to call to
12232301SN/A     * matter how data was allocted.
12242301SN/A     */
12252301SN/A    void
12262301SN/A    deleteData()
12272301SN/A    {
12282301SN/A        if (flags.isSet(DYNAMIC_DATA))
12296221Snate@binkert.org            delete [] data;
12302301SN/A
12316221Snate@binkert.org        flags.clear(STATIC_DATA|DYNAMIC_DATA);
12322301SN/A        data = NULL;
12332301SN/A    }
12346221Snate@binkert.org
12352301SN/A    /** Allocate memory for the packet. */
12362301SN/A    void
12372301SN/A    allocate()
12382301SN/A    {
12392301SN/A        // if either this command or the response command has a data
12402301SN/A        // payload, actually allocate space
12416221Snate@binkert.org        if (hasData() || hasRespData()) {
12422301SN/A            assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
12432301SN/A            flags.set(DYNAMIC_DATA);
12442301SN/A            data = new uint8_t[getSize()];
12452301SN/A        }
12462301SN/A    }
12476221Snate@binkert.org
12482301SN/A    /** @} */
12492301SN/A
12506221Snate@binkert.org    /** Get the data in the packet without byte swapping. */
12512301SN/A    template <typename T>
12522301SN/A    T getRaw() const;
12532301SN/A
12542301SN/A    /** Set the value in the data pointer to v without byte swapping. */
12556221Snate@binkert.org    template <typename T>
12562301SN/A    void setRaw(T v);
12572301SN/A
12582301SN/A  public:
12592292SN/A    /**
12602292SN/A     * Check a functional request against a memory value stored in
12612316SN/A     * another packet (i.e. an in-transit request or
12622292SN/A     * response). Returns true if the current packet is a read, and
12632292SN/A     * the other packet provides the data, which is then copied to the
12642292SN/A     * current packet. If the current packet is a write, and the other
12656221Snate@binkert.org     * packet intersects this one, then we update the data
12662292SN/A     * accordingly.
12672292SN/A     */
12682292SN/A    bool
12692292SN/A    trySatisfyFunctional(PacketPtr other)
12702292SN/A    {
12712292SN/A        // all packets that are carrying a payload should have a valid
12722292SN/A        // data pointer
12732292SN/A        return trySatisfyFunctional(other, other->getAddr(), other->isSecure(),
12742292SN/A                                    other->getSize(),
12752292SN/A                                    other->hasData() ?
12762292SN/A                                    other->getPtr<uint8_t>() : NULL);
12772292SN/A    }
12782292SN/A
12792292SN/A    /**
12802292SN/A     * Does the request need to check for cached copies of the same block
12812292SN/A     * in the memory hierarchy above.
12822292SN/A     **/
12832292SN/A    bool
12846221Snate@binkert.org    mustCheckAbove() const
12852292SN/A    {
12862292SN/A        return cmd == MemCmd::HardPFReq || isEviction();
12873867Sbinkertn@umich.edu    }
12886221Snate@binkert.org
12892292SN/A    /**
12902292SN/A     * Is this packet a clean eviction, including both actual clean
12912292SN/A     * evict packets, but also clean writebacks.
12922292SN/A     */
12932292SN/A    bool
12942292SN/A    isCleanEviction() const
12956221Snate@binkert.org    {
12962292SN/A        return cmd == MemCmd::CleanEvict || cmd == MemCmd::WritebackClean;
12972292SN/A    }
12982292SN/A
12992292SN/A    /**
13002292SN/A     * Check a functional request against a memory value represented
13016221Snate@binkert.org     * by a base/size pair and an associated data array. If the
13022292SN/A     * current packet is a read, it may be satisfied by the memory
13032292SN/A     * value. If the current packet is a write, it may update the
13046221Snate@binkert.org     * memory value.
13056221Snate@binkert.org     */
13062292SN/A    bool
13072292SN/A    trySatisfyFunctional(Printable *obj, Addr base, bool is_secure, int size,
13086221Snate@binkert.org                         uint8_t *_data);
13092292SN/A
13102292SN/A    /**
13112831Sksewell@umich.edu     * Push label for PrintReq (safe to call unconditionally).
13122831Sksewell@umich.edu     */
13132292SN/A    void
13142292SN/A    pushLabel(const std::string &lbl)
13152292SN/A    {
13162292SN/A        if (isPrint())
13172292SN/A            safe_cast<PrintReqState*>(senderState)->pushLabel(lbl);
13182292SN/A    }
13192292SN/A
13202292SN/A    /**
13212292SN/A     * Pop label for PrintReq (safe to call unconditionally).
13222292SN/A     */
13232292SN/A    void
13242292SN/A    popLabel()
13256221Snate@binkert.org    {
13262292SN/A        if (isPrint())
13272292SN/A            safe_cast<PrintReqState*>(senderState)->popLabel();
13282292SN/A    }
13296221Snate@binkert.org
13302292SN/A    void print(std::ostream &o, int verbosity = 0,
13312292SN/A               const std::string &prefix = "") const;
13322292SN/A
13332292SN/A    /**
13342292SN/A     * A no-args wrapper of print(std::ostream...)
13356221Snate@binkert.org     * meant to be invoked from DPRINTFs
13366221Snate@binkert.org     * avoiding string overheads in fast mode
13372292SN/A     * @return string with the request's type and start<->end addresses
13383867Sbinkertn@umich.edu     */
13396221Snate@binkert.org    std::string print() const;
13402292SN/A};
13412292SN/A
13422292SN/A#endif //__MEM_PACKET_HH
13432292SN/A