packet.hh revision 9031
14120Sgblack@eecs.umich.edu/*
24120Sgblack@eecs.umich.edu * Copyright (c) 2012 ARM Limited
34120Sgblack@eecs.umich.edu * All rights reserved
44120Sgblack@eecs.umich.edu *
57087Snate@binkert.org * The license below extends only to copyright in the software and shall
67087Snate@binkert.org * not be construed as granting a license to any other intellectual
77087Snate@binkert.org * property including but not limited to intellectual property relating
87087Snate@binkert.org * to a hardware implementation of the functionality of the software
97087Snate@binkert.org * licensed hereunder.  You may use the software subject to the license
107087Snate@binkert.org * terms below provided that you ensure that this notice is replicated
117087Snate@binkert.org * unmodified and in its entirety in all distributions of the software,
127087Snate@binkert.org * modified or unmodified, in source code or in binary form.
134120Sgblack@eecs.umich.edu *
147087Snate@binkert.org * Copyright (c) 2006 The Regents of The University of Michigan
157087Snate@binkert.org * Copyright (c) 2010 Advanced Micro Devices, Inc.
167087Snate@binkert.org * All rights reserved.
177087Snate@binkert.org *
187087Snate@binkert.org * Redistribution and use in source and binary forms, with or without
197087Snate@binkert.org * modification, are permitted provided that the following conditions are
207087Snate@binkert.org * met: redistributions of source code must retain the above copyright
217087Snate@binkert.org * notice, this list of conditions and the following disclaimer;
224120Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
237087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
244120Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
254120Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
264120Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
274120Sgblack@eecs.umich.edu * this software without specific prior written permission.
284120Sgblack@eecs.umich.edu *
294120Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
304120Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
314120Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
324120Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
334120Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
344120Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
354120Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
364120Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
374120Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
384120Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
394120Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
404120Sgblack@eecs.umich.edu *
414120Sgblack@eecs.umich.edu * Authors: Ron Dreslinski
424120Sgblack@eecs.umich.edu *          Steve Reinhardt
435086Sgblack@eecs.umich.edu *          Ali Saidi
445655Sgblack@eecs.umich.edu *          Andreas Hansson
457629Sgblack@eecs.umich.edu */
465654Sgblack@eecs.umich.edu
475086Sgblack@eecs.umich.edu/**
485648Sgblack@eecs.umich.edu * @file
495651Sgblack@eecs.umich.edu * Declaration of the Packet class.
505647Sgblack@eecs.umich.edu */
515647Sgblack@eecs.umich.edu
525647Sgblack@eecs.umich.edu#ifndef __MEM_PACKET_HH__
535647Sgblack@eecs.umich.edu#define __MEM_PACKET_HH__
545810Sgblack@eecs.umich.edu
554120Sgblack@eecs.umich.edu#include <bitset>
565704Snate@binkert.org#include <cassert>
575086Sgblack@eecs.umich.edu#include <list>
585651Sgblack@eecs.umich.edu
595086Sgblack@eecs.umich.edu#include "base/cast.hh"
605647Sgblack@eecs.umich.edu#include "base/compiler.hh"
615654Sgblack@eecs.umich.edu#include "base/fast_alloc.hh"
625647Sgblack@eecs.umich.edu#include "base/flags.hh"
635654Sgblack@eecs.umich.edu#include "base/misc.hh"
645691Sgblack@eecs.umich.edu#include "base/printable.hh"
655691Sgblack@eecs.umich.edu#include "base/types.hh"
665691Sgblack@eecs.umich.edu#include "mem/request.hh"
675691Sgblack@eecs.umich.edu#include "sim/core.hh"
685691Sgblack@eecs.umich.edu
695691Sgblack@eecs.umich.educlass Packet;
705691Sgblack@eecs.umich.edutypedef Packet *PacketPtr;
715691Sgblack@eecs.umich.edutypedef uint8_t* PacketDataPtr;
725691Sgblack@eecs.umich.edutypedef std::list<PacketPtr> PacketList;
735691Sgblack@eecs.umich.edu
745691Sgblack@eecs.umich.educlass MemCmd
755654Sgblack@eecs.umich.edu{
765654Sgblack@eecs.umich.edu    friend class Packet;
775654Sgblack@eecs.umich.edu
785648Sgblack@eecs.umich.edu  public:
795648Sgblack@eecs.umich.edu    /**
805647Sgblack@eecs.umich.edu     * List of all commands associated with a packet.
815647Sgblack@eecs.umich.edu     */
825647Sgblack@eecs.umich.edu    enum Command
835691Sgblack@eecs.umich.edu    {
845691Sgblack@eecs.umich.edu        InvalidCmd,
855647Sgblack@eecs.umich.edu        ReadReq,
865691Sgblack@eecs.umich.edu        ReadResp,
875691Sgblack@eecs.umich.edu        ReadRespWithInvalidate,
885647Sgblack@eecs.umich.edu        WriteReq,
895647Sgblack@eecs.umich.edu        WriteResp,
905647Sgblack@eecs.umich.edu        Writeback,
915647Sgblack@eecs.umich.edu        SoftPFReq,
925691Sgblack@eecs.umich.edu        HardPFReq,
935691Sgblack@eecs.umich.edu        SoftPFResp,
945691Sgblack@eecs.umich.edu        HardPFResp,
955691Sgblack@eecs.umich.edu        // WriteInvalidateReq transactions used to be generated by the
965691Sgblack@eecs.umich.edu        // DMA ports when writing full blocks to memory, however, it
975647Sgblack@eecs.umich.edu        // is not used anymore since we put the I/O cache in place to
985647Sgblack@eecs.umich.edu        // deal with partial block writes. Hence, WriteInvalidateReq
995647Sgblack@eecs.umich.edu        // and WriteInvalidateResp are currently unused. The
1005647Sgblack@eecs.umich.edu        // implication is that the I/O cache does read-exclusive
1015647Sgblack@eecs.umich.edu        // operations on every full-cache-block DMA, and ultimately
1025654Sgblack@eecs.umich.edu        // this needs to be fixed.
1035655Sgblack@eecs.umich.edu        WriteInvalidateReq,
1045655Sgblack@eecs.umich.edu        WriteInvalidateResp,
1055655Sgblack@eecs.umich.edu        UpgradeReq,
1065655Sgblack@eecs.umich.edu        SCUpgradeReq,           // Special "weak" upgrade for StoreCond
1075691Sgblack@eecs.umich.edu        UpgradeResp,
1085655Sgblack@eecs.umich.edu        SCUpgradeFailReq,       // Failed SCUpgradeReq in MSHR (never sent)
1095691Sgblack@eecs.umich.edu        UpgradeFailResp,        // Valid for SCUpgradeReq only
1105655Sgblack@eecs.umich.edu        ReadExReq,
1115691Sgblack@eecs.umich.edu        ReadExResp,
1125655Sgblack@eecs.umich.edu        LoadLockedReq,
1135691Sgblack@eecs.umich.edu        StoreCondReq,
1146050Sgblack@eecs.umich.edu        StoreCondFailReq,       // Failed StoreCondReq in MSHR (never sent)
1156050Sgblack@eecs.umich.edu        StoreCondResp,
1166066Sgblack@eecs.umich.edu        SwapReq,
1175655Sgblack@eecs.umich.edu        SwapResp,
1185655Sgblack@eecs.umich.edu        MessageReq,
1195655Sgblack@eecs.umich.edu        MessageResp,
1205655Sgblack@eecs.umich.edu        // Error responses
1216069Sgblack@eecs.umich.edu        // @TODO these should be classified as responses rather than
1226069Sgblack@eecs.umich.edu        // requests; coding them as requests initially for backwards
1236069Sgblack@eecs.umich.edu        // compatibility
1245655Sgblack@eecs.umich.edu        NetworkNackError,  // nacked at network layer (not by protocol)
1255654Sgblack@eecs.umich.edu        InvalidDestError,  // packet dest field invalid
1265654Sgblack@eecs.umich.edu        BadAddressError,   // memory address invalid
1275654Sgblack@eecs.umich.edu        FunctionalReadError, // unable to fulfill functional read
1285654Sgblack@eecs.umich.edu        FunctionalWriteError, // unable to fulfill functional write
1295654Sgblack@eecs.umich.edu        // Fake simulator-only commands
1305654Sgblack@eecs.umich.edu        PrintReq,       // Print state matching address
1315654Sgblack@eecs.umich.edu        FlushReq,      //request for a cache flush
1325654Sgblack@eecs.umich.edu        InvalidationReq,   // request for address to be invalidated from lsq
1335654Sgblack@eecs.umich.edu        NUM_MEM_CMDS
1345654Sgblack@eecs.umich.edu    };
1355654Sgblack@eecs.umich.edu
1365654Sgblack@eecs.umich.edu  private:
1375654Sgblack@eecs.umich.edu    /**
1385654Sgblack@eecs.umich.edu     * List of command attributes.
1395654Sgblack@eecs.umich.edu     */
1405654Sgblack@eecs.umich.edu    enum Attribute
1415654Sgblack@eecs.umich.edu    {
1425654Sgblack@eecs.umich.edu        IsRead,         //!< Data flows from responder to requester
1435654Sgblack@eecs.umich.edu        IsWrite,        //!< Data flows from requester to responder
1445654Sgblack@eecs.umich.edu        IsUpgrade,
1455654Sgblack@eecs.umich.edu        IsInvalidate,
1465654Sgblack@eecs.umich.edu        NeedsExclusive, //!< Requires exclusive copy to complete in-cache
1475654Sgblack@eecs.umich.edu        IsRequest,      //!< Issued by requester
1485654Sgblack@eecs.umich.edu        IsResponse,     //!< Issue by responder
1495654Sgblack@eecs.umich.edu        NeedsResponse,  //!< Requester needs response from target
1505654Sgblack@eecs.umich.edu        IsSWPrefetch,
1515654Sgblack@eecs.umich.edu        IsHWPrefetch,
1525654Sgblack@eecs.umich.edu        IsLlsc,         //!< Alpha/MIPS LL or SC access
1535654Sgblack@eecs.umich.edu        HasData,        //!< There is an associated payload
1545654Sgblack@eecs.umich.edu        IsError,        //!< Error response
1555654Sgblack@eecs.umich.edu        IsPrint,        //!< Print state matching address (for debugging)
1565654Sgblack@eecs.umich.edu        IsFlush,        //!< Flush the address from caches
1576101Sgblack@eecs.umich.edu        NUM_COMMAND_ATTRIBUTES
1585654Sgblack@eecs.umich.edu    };
1595654Sgblack@eecs.umich.edu
1605654Sgblack@eecs.umich.edu    /**
1615654Sgblack@eecs.umich.edu     * Structure that defines attributes and other data associated
1625654Sgblack@eecs.umich.edu     * with a Command.
1636101Sgblack@eecs.umich.edu     */
1645654Sgblack@eecs.umich.edu    struct CommandInfo
1655654Sgblack@eecs.umich.edu    {
1665654Sgblack@eecs.umich.edu        /// Set of attribute flags.
1675654Sgblack@eecs.umich.edu        const std::bitset<NUM_COMMAND_ATTRIBUTES> attributes;
1685654Sgblack@eecs.umich.edu        /// Corresponding response for requests; InvalidCmd if no
1696101Sgblack@eecs.umich.edu        /// response is applicable.
1705654Sgblack@eecs.umich.edu        const Command response;
1715654Sgblack@eecs.umich.edu        /// String representation (for printing)
1725691Sgblack@eecs.umich.edu        const std::string str;
1735691Sgblack@eecs.umich.edu    };
1745810Sgblack@eecs.umich.edu
1755810Sgblack@eecs.umich.edu    /// Array to map Command enum to associated info.
1766136Sgblack@eecs.umich.edu    static const CommandInfo commandInfo[];
1776136Sgblack@eecs.umich.edu
1785086Sgblack@eecs.umich.edu  private:
1795654Sgblack@eecs.umich.edu
1805654Sgblack@eecs.umich.edu    Command cmd;
1815654Sgblack@eecs.umich.edu
1825647Sgblack@eecs.umich.edu    bool
1835647Sgblack@eecs.umich.edu    testCmdAttrib(MemCmd::Attribute attrib) const
1846041Sgblack@eecs.umich.edu    {
1855810Sgblack@eecs.umich.edu        return commandInfo[cmd].attributes[attrib] != 0;
1865810Sgblack@eecs.umich.edu    }
1875704Snate@binkert.org
1885648Sgblack@eecs.umich.edu  public:
1895648Sgblack@eecs.umich.edu
1905648Sgblack@eecs.umich.edu    bool isRead() const         { return testCmdAttrib(IsRead); }
1915648Sgblack@eecs.umich.edu    bool isWrite() const        { return testCmdAttrib(IsWrite); }
1925647Sgblack@eecs.umich.edu    bool isUpgrade() const      { return testCmdAttrib(IsUpgrade); }
1935647Sgblack@eecs.umich.edu    bool isRequest() const      { return testCmdAttrib(IsRequest); }
1945086Sgblack@eecs.umich.edu    bool isResponse() const     { return testCmdAttrib(IsResponse); }
1955647Sgblack@eecs.umich.edu    bool needsExclusive() const { return testCmdAttrib(NeedsExclusive); }
1965647Sgblack@eecs.umich.edu    bool needsResponse() const  { return testCmdAttrib(NeedsResponse); }
1975647Sgblack@eecs.umich.edu    bool isInvalidate() const   { return testCmdAttrib(IsInvalidate); }
1985654Sgblack@eecs.umich.edu    bool hasData() const        { return testCmdAttrib(HasData); }
1996137Sgblack@eecs.umich.edu    bool isReadWrite() const    { return isRead() && isWrite(); }
2006137Sgblack@eecs.umich.edu    bool isLLSC() const         { return testCmdAttrib(IsLlsc); }
2016137Sgblack@eecs.umich.edu    bool isError() const        { return testCmdAttrib(IsError); }
2026137Sgblack@eecs.umich.edu    bool isPrint() const        { return testCmdAttrib(IsPrint); }
2036137Sgblack@eecs.umich.edu    bool isFlush() const        { return testCmdAttrib(IsFlush); }
2045654Sgblack@eecs.umich.edu
2055654Sgblack@eecs.umich.edu    const Command
2065648Sgblack@eecs.umich.edu    responseCommand() const
2075648Sgblack@eecs.umich.edu    {
2085651Sgblack@eecs.umich.edu        return commandInfo[cmd].response;
2096064Sgblack@eecs.umich.edu    }
2105647Sgblack@eecs.umich.edu
2115691Sgblack@eecs.umich.edu    /// Return the string to a cmd given by idx.
2125691Sgblack@eecs.umich.edu    const std::string &toString() const { return commandInfo[cmd].str; }
2135691Sgblack@eecs.umich.edu    int toInt() const { return (int)cmd; }
2145691Sgblack@eecs.umich.edu
2155691Sgblack@eecs.umich.edu    MemCmd(Command _cmd) : cmd(_cmd) { }
2165691Sgblack@eecs.umich.edu    MemCmd(int _cmd) : cmd((Command)_cmd) { }
2175691Sgblack@eecs.umich.edu    MemCmd() : cmd(InvalidCmd) { }
2185691Sgblack@eecs.umich.edu
2195691Sgblack@eecs.umich.edu    bool operator==(MemCmd c2) const { return (cmd == c2.cmd); }
2206041Sgblack@eecs.umich.edu    bool operator!=(MemCmd c2) const { return (cmd != c2.cmd); }
2216041Sgblack@eecs.umich.edu};
2225651Sgblack@eecs.umich.edu
2235654Sgblack@eecs.umich.edu/**
2245654Sgblack@eecs.umich.edu * A Packet is used to encapsulate a transfer between two objects in
2255654Sgblack@eecs.umich.edu * the memory system (e.g., the L1 and L2 cache).  (In contrast, a
2265654Sgblack@eecs.umich.edu * single Request travels all the way from the requester to the
2275654Sgblack@eecs.umich.edu * ultimate destination and back, possibly being conveyed by several
2285654Sgblack@eecs.umich.edu * different Packets along the way.)
2295654Sgblack@eecs.umich.edu */
2305654Sgblack@eecs.umich.educlass Packet : public FastAlloc, public Printable
2315654Sgblack@eecs.umich.edu{
2325654Sgblack@eecs.umich.edu  public:
2335654Sgblack@eecs.umich.edu    typedef uint32_t FlagsType;
2345648Sgblack@eecs.umich.edu    typedef ::Flags<FlagsType> Flags;
2355648Sgblack@eecs.umich.edu
2365704Snate@binkert.org  private:
2375704Snate@binkert.org    static const FlagsType PUBLIC_FLAGS           = 0x00000000;
2385647Sgblack@eecs.umich.edu    static const FlagsType PRIVATE_FLAGS          = 0x00007F0F;
2395648Sgblack@eecs.umich.edu    static const FlagsType COPY_FLAGS             = 0x0000000F;
2405648Sgblack@eecs.umich.edu
2415648Sgblack@eecs.umich.edu    static const FlagsType SHARED                 = 0x00000001;
2425654Sgblack@eecs.umich.edu    // Special control flags
2435654Sgblack@eecs.umich.edu    /// Special timing-mode atomic snoop for multi-level coherence.
2445654Sgblack@eecs.umich.edu    static const FlagsType EXPRESS_SNOOP          = 0x00000002;
2455654Sgblack@eecs.umich.edu    /// Does supplier have exclusive copy?
2466041Sgblack@eecs.umich.edu    /// Useful for multi-level coherence.
2475086Sgblack@eecs.umich.edu    static const FlagsType SUPPLY_EXCLUSIVE       = 0x00000004;
2485654Sgblack@eecs.umich.edu    // Snoop response flags
2495654Sgblack@eecs.umich.edu    static const FlagsType MEM_INHIBIT            = 0x00000008;
2505654Sgblack@eecs.umich.edu    /// Are the 'addr' and 'size' fields valid?
2515651Sgblack@eecs.umich.edu    static const FlagsType VALID_ADDR             = 0x00000100;
2525704Snate@binkert.org    static const FlagsType VALID_SIZE             = 0x00000200;
2535704Snate@binkert.org    /// Is the data pointer set to a value that shouldn't be freed
2545704Snate@binkert.org    /// when the packet is destroyed?
2555086Sgblack@eecs.umich.edu    static const FlagsType STATIC_DATA            = 0x00001000;
2565654Sgblack@eecs.umich.edu    /// The data pointer points to a value that should be freed when
2575654Sgblack@eecs.umich.edu    /// the packet is destroyed.
2585654Sgblack@eecs.umich.edu    static const FlagsType DYNAMIC_DATA           = 0x00002000;
2595086Sgblack@eecs.umich.edu    /// the data pointer points to an array (thus delete []) needs to
2607902Shestness@cs.utexas.edu    /// be called on it rather than simply delete.
2617902Shestness@cs.utexas.edu    static const FlagsType ARRAY_DATA             = 0x00004000;
2625654Sgblack@eecs.umich.edu    /// suppress the error if this packet encounters a functional
2635654Sgblack@eecs.umich.edu    /// access failure.
2645654Sgblack@eecs.umich.edu    static const FlagsType SUPPRESS_FUNC_ERROR    = 0x00008000;
2655654Sgblack@eecs.umich.edu
2665654Sgblack@eecs.umich.edu    Flags flags;
2675704Snate@binkert.org
2685704Snate@binkert.org  public:
2695654Sgblack@eecs.umich.edu    typedef MemCmd::Command Command;
2705654Sgblack@eecs.umich.edu
2715654Sgblack@eecs.umich.edu    /// The command field of the packet.
2725654Sgblack@eecs.umich.edu    MemCmd cmd;
2735704Snate@binkert.org
2745704Snate@binkert.org    /// A pointer to the original request.
2755654Sgblack@eecs.umich.edu    RequestPtr req;
2765654Sgblack@eecs.umich.edu
2775654Sgblack@eecs.umich.edu  private:
2785654Sgblack@eecs.umich.edu   /**
2795704Snate@binkert.org    * A pointer to the data being transfered.  It can be differnt
2805704Snate@binkert.org    * sizes at each level of the heirarchy so it belongs in the
2815654Sgblack@eecs.umich.edu    * packet, not request. This may or may not be populated when a
2825704Snate@binkert.org    * responder recieves the packet. If not populated it memory should
2835654Sgblack@eecs.umich.edu    * be allocated.
2845086Sgblack@eecs.umich.edu    */
2855086Sgblack@eecs.umich.edu    PacketDataPtr data;
2865704Snate@binkert.org
2874120Sgblack@eecs.umich.edu    /// The address of the request.  This address could be virtual or
2884120Sgblack@eecs.umich.edu    /// physical, depending on the system configuration.
289    Addr addr;
290
291    /// The size of the request or transfer.
292    unsigned size;
293
294    /**
295     * Source port identifier set on a request packet to enable
296     * appropriate routing of the responses. The source port
297     * identifier is set by any multiplexing component, e.g. a bus, as
298     * the timing responses need this information to be routed back to
299     * the appropriate port at a later point in time. The field can be
300     * updated (over-written) as the request packet passes through
301     * additional multiplexing components, and it is their
302     * responsibility to remember the original source port identifier,
303     * for example by using an appropriate sender state. The latter is
304     * done in the cache and bridge.
305     */
306    PortID src;
307
308    /**
309     * Destination port identifier that is present on all response
310     * packets that passed through a multiplexing component as a
311     * request packet. The source port identifier is turned into a
312     * destination port identifier when the packet is turned into a
313     * response, and the destination is used, e.g. by the bus, to
314     * select the appropriate path through the interconnect.
315     */
316    PortID dest;
317
318    /**
319     * The original value of the command field.  Only valid when the
320     * current command field is an error condition; in that case, the
321     * previous contents of the command field are copied here.  This
322     * field is *not* set on non-error responses.
323     */
324    MemCmd origCmd;
325
326    /**
327     * These values specify the range of bytes found that satisfy a
328     * functional read.
329     */
330    uint16_t bytesValidStart;
331    uint16_t bytesValidEnd;
332
333  public:
334    /// Used to calculate latencies for each packet.
335    Tick time;
336
337    /// The time at which the packet will be fully transmitted
338    Tick finishTime;
339
340    /// The time at which the first chunk of the packet will be transmitted
341    Tick firstWordTime;
342
343    /**
344     * A virtual base opaque structure used to hold state associated
345     * with the packet but specific to the sending device (e.g., an
346     * MSHR).  A pointer to this state is returned in the packet's
347     * response so that the sender can quickly look up the state
348     * needed to process it.  A specific subclass would be derived
349     * from this to carry state specific to a particular sending
350     * device.
351     */
352    struct SenderState
353    {
354        virtual ~SenderState() {}
355    };
356
357    /**
358     * Object used to maintain state of a PrintReq.  The senderState
359     * field of a PrintReq should always be of this type.
360     */
361    class PrintReqState : public SenderState, public FastAlloc
362    {
363      private:
364        /**
365         * An entry in the label stack.
366         */
367        struct LabelStackEntry
368        {
369            const std::string label;
370            std::string *prefix;
371            bool labelPrinted;
372            LabelStackEntry(const std::string &_label, std::string *_prefix);
373        };
374
375        typedef std::list<LabelStackEntry> LabelStack;
376        LabelStack labelStack;
377
378        std::string *curPrefixPtr;
379
380      public:
381        std::ostream &os;
382        const int verbosity;
383
384        PrintReqState(std::ostream &os, int verbosity = 0);
385        ~PrintReqState();
386
387        /**
388         * Returns the current line prefix.
389         */
390        const std::string &curPrefix() { return *curPrefixPtr; }
391
392        /**
393         * Push a label onto the label stack, and prepend the given
394         * prefix string onto the current prefix.  Labels will only be
395         * printed if an object within the label's scope is printed.
396         */
397        void pushLabel(const std::string &lbl,
398                       const std::string &prefix = "  ");
399
400        /**
401         * Pop a label off the label stack.
402         */
403        void popLabel();
404
405        /**
406         * Print all of the pending unprinted labels on the
407         * stack. Called by printObj(), so normally not called by
408         * users unless bypassing printObj().
409         */
410        void printLabels();
411
412        /**
413         * Print a Printable object to os, because it matched the
414         * address on a PrintReq.
415         */
416        void printObj(Printable *obj);
417    };
418
419    /**
420     * This packet's sender state.  Devices should use dynamic_cast<>
421     * to cast to the state appropriate to the sender.  The intent of
422     * this variable is to allow a device to attach extra information
423     * to a request.  A response packet must return the sender state
424     * that was attached to the original request (even if a new packet
425     * is created).
426     */
427    SenderState *senderState;
428
429    /// Return the string name of the cmd field (for debugging and
430    /// tracing).
431    const std::string &cmdString() const { return cmd.toString(); }
432
433    /// Return the index of this command.
434    inline int cmdToIndex() const { return cmd.toInt(); }
435
436    bool isRead() const         { return cmd.isRead(); }
437    bool isWrite() const        { return cmd.isWrite(); }
438    bool isUpgrade()  const     { return cmd.isUpgrade(); }
439    bool isRequest() const      { return cmd.isRequest(); }
440    bool isResponse() const     { return cmd.isResponse(); }
441    bool needsExclusive() const { return cmd.needsExclusive(); }
442    bool needsResponse() const  { return cmd.needsResponse(); }
443    bool isInvalidate() const   { return cmd.isInvalidate(); }
444    bool hasData() const        { return cmd.hasData(); }
445    bool isReadWrite() const    { return cmd.isReadWrite(); }
446    bool isLLSC() const         { return cmd.isLLSC(); }
447    bool isError() const        { return cmd.isError(); }
448    bool isPrint() const        { return cmd.isPrint(); }
449    bool isFlush() const        { return cmd.isFlush(); }
450
451    // Snoop flags
452    void assertMemInhibit()     { flags.set(MEM_INHIBIT); }
453    bool memInhibitAsserted()   { return flags.isSet(MEM_INHIBIT); }
454    void assertShared()         { flags.set(SHARED); }
455    bool sharedAsserted()       { return flags.isSet(SHARED); }
456
457    // Special control flags
458    void setExpressSnoop()      { flags.set(EXPRESS_SNOOP); }
459    bool isExpressSnoop()       { return flags.isSet(EXPRESS_SNOOP); }
460    void setSupplyExclusive()   { flags.set(SUPPLY_EXCLUSIVE); }
461    void clearSupplyExclusive() { flags.clear(SUPPLY_EXCLUSIVE); }
462    bool isSupplyExclusive()    { return flags.isSet(SUPPLY_EXCLUSIVE); }
463    void setSuppressFuncError() { flags.set(SUPPRESS_FUNC_ERROR); }
464    bool suppressFuncError()    { return flags.isSet(SUPPRESS_FUNC_ERROR); }
465
466    // Network error conditions... encapsulate them as methods since
467    // their encoding keeps changing (from result field to command
468    // field, etc.)
469    void
470    setNacked()
471    {
472        assert(isResponse());
473        cmd = MemCmd::NetworkNackError;
474    }
475
476    void
477    setBadAddress()
478    {
479        assert(isResponse());
480        cmd = MemCmd::BadAddressError;
481    }
482
483    bool wasNacked() const     { return cmd == MemCmd::NetworkNackError; }
484    bool hadBadAddress() const { return cmd == MemCmd::BadAddressError; }
485    void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; }
486
487    bool isSrcValid() const { return src != InvalidPortID; }
488    /// Accessor function to get the source index of the packet.
489    PortID getSrc() const { assert(isSrcValid()); return src; }
490    /// Accessor function to set the source index of the packet.
491    void setSrc(PortID _src) { src = _src; }
492    /// Reset source field, e.g. to retransmit packet on different bus.
493    void clearSrc() { src = InvalidPortID; }
494
495    bool isDestValid() const { return dest != InvalidPortID; }
496    /// Accessor function for the destination index of the packet.
497    PortID getDest() const { assert(isDestValid()); return dest; }
498    /// Accessor function to set the destination index of the packet.
499    void setDest(PortID _dest) { dest = _dest; }
500    /// Reset destination field, e.g. to turn a response into a request again.
501    void clearDest() { dest = InvalidPortID; }
502
503    Addr getAddr() const { assert(flags.isSet(VALID_ADDR)); return addr; }
504    unsigned getSize() const  { assert(flags.isSet(VALID_SIZE)); return size; }
505    Addr getOffset(int blkSize) const { return getAddr() & (Addr)(blkSize - 1); }
506
507    /**
508     * It has been determined that the SC packet should successfully update
509     * memory.  Therefore, convert this SC packet to a normal write.
510     */
511    void
512    convertScToWrite()
513    {
514        assert(isLLSC());
515        assert(isWrite());
516        cmd = MemCmd::WriteReq;
517    }
518
519    /**
520     * When ruby is in use, Ruby will monitor the cache line and thus M5
521     * phys memory should treat LL ops as normal reads.
522     */
523    void
524    convertLlToRead()
525    {
526        assert(isLLSC());
527        assert(isRead());
528        cmd = MemCmd::ReadReq;
529    }
530
531    /**
532     * Constructor.  Note that a Request object must be constructed
533     * first, but the Requests's physical address and size fields need
534     * not be valid. The command must be supplied.
535     */
536    Packet(Request *_req, MemCmd _cmd)
537        :  cmd(_cmd), req(_req), data(NULL),
538           src(InvalidPortID), dest(InvalidPortID),
539           bytesValidStart(0), bytesValidEnd(0),
540           time(curTick()), senderState(NULL)
541    {
542        if (req->hasPaddr()) {
543            addr = req->getPaddr();
544            flags.set(VALID_ADDR);
545        }
546        if (req->hasSize()) {
547            size = req->getSize();
548            flags.set(VALID_SIZE);
549        }
550    }
551
552    /**
553     * Alternate constructor if you are trying to create a packet with
554     * a request that is for a whole block, not the address from the
555     * req.  this allows for overriding the size/addr of the req.
556     */
557    Packet(Request *_req, MemCmd _cmd, int _blkSize)
558        :  cmd(_cmd), req(_req), data(NULL),
559           src(InvalidPortID), dest(InvalidPortID),
560           bytesValidStart(0), bytesValidEnd(0),
561           time(curTick()), senderState(NULL)
562    {
563        if (req->hasPaddr()) {
564            addr = req->getPaddr() & ~(_blkSize - 1);
565            flags.set(VALID_ADDR);
566        }
567        size = _blkSize;
568        flags.set(VALID_SIZE);
569    }
570
571    /**
572     * Alternate constructor for copying a packet.  Copy all fields
573     * *except* if the original packet's data was dynamic, don't copy
574     * that, as we can't guarantee that the new packet's lifetime is
575     * less than that of the original packet.  In this case the new
576     * packet should allocate its own data.
577     */
578    Packet(Packet *pkt, bool clearFlags = false)
579        :  cmd(pkt->cmd), req(pkt->req),
580           data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL),
581           addr(pkt->addr), size(pkt->size), src(pkt->src), dest(pkt->dest),
582           bytesValidStart(pkt->bytesValidStart), bytesValidEnd(pkt->bytesValidEnd),
583           time(curTick()), senderState(pkt->senderState)
584    {
585        if (!clearFlags)
586            flags.set(pkt->flags & COPY_FLAGS);
587
588        flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE));
589        flags.set(pkt->flags & STATIC_DATA);
590
591    }
592
593    /**
594     * clean up packet variables
595     */
596    ~Packet()
597    {
598        // If this is a request packet for which there's no response,
599        // delete the request object here, since the requester will
600        // never get the chance.
601        if (req && isRequest() && !needsResponse())
602            delete req;
603        deleteData();
604    }
605
606    /**
607     * Reinitialize packet address and size from the associated
608     * Request object, and reset other fields that may have been
609     * modified by a previous transaction.  Typically called when a
610     * statically allocated Request/Packet pair is reused for multiple
611     * transactions.
612     */
613    void
614    reinitFromRequest()
615    {
616        assert(req->hasPaddr());
617        flags = 0;
618        addr = req->getPaddr();
619        size = req->getSize();
620        time = req->time();
621
622        flags.set(VALID_ADDR|VALID_SIZE);
623        deleteData();
624    }
625
626    /**
627     * Take a request packet and modify it in place to be suitable for
628     * returning as a response to that request. The source field is
629     * turned into the destination, and subsequently cleared. Note
630     * that the latter is not necessary for atomic requests, but
631     * causes no harm as neither field is valid.
632     */
633    void
634    makeResponse()
635    {
636        assert(needsResponse());
637        assert(isRequest());
638        origCmd = cmd;
639        cmd = cmd.responseCommand();
640
641        // responses are never express, even if the snoop that
642        // triggered them was
643        flags.clear(EXPRESS_SNOOP);
644
645        dest = src;
646        clearSrc();
647    }
648
649    void
650    makeAtomicResponse()
651    {
652        makeResponse();
653    }
654
655    void
656    makeTimingResponse()
657    {
658        makeResponse();
659    }
660
661    void
662    setFunctionalResponseStatus(bool success)
663    {
664        if (!success) {
665            if (isWrite()) {
666                cmd = MemCmd::FunctionalWriteError;
667            } else {
668                cmd = MemCmd::FunctionalReadError;
669            }
670        }
671    }
672
673    /**
674     * Take a request packet that has been returned as NACKED and
675     * modify it so that it can be sent out again. Only packets that
676     * need a response can be NACKED, so verify that that is true.
677     */
678    void
679    reinitNacked()
680    {
681        assert(wasNacked());
682        cmd = origCmd;
683        assert(needsResponse());
684        clearDest();
685    }
686
687    void
688    setSize(unsigned size)
689    {
690        assert(!flags.isSet(VALID_SIZE));
691
692        this->size = size;
693        flags.set(VALID_SIZE);
694    }
695
696
697    /**
698     * Set the data pointer to the following value that should not be
699     * freed.
700     */
701    template <typename T>
702    void
703    dataStatic(T *p)
704    {
705        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
706        data = (PacketDataPtr)p;
707        flags.set(STATIC_DATA);
708    }
709
710    /**
711     * Set the data pointer to a value that should have delete []
712     * called on it.
713     */
714    template <typename T>
715    void
716    dataDynamicArray(T *p)
717    {
718        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
719        data = (PacketDataPtr)p;
720        flags.set(DYNAMIC_DATA|ARRAY_DATA);
721    }
722
723    /**
724     * set the data pointer to a value that should have delete called
725     * on it.
726     */
727    template <typename T>
728    void
729    dataDynamic(T *p)
730    {
731        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
732        data = (PacketDataPtr)p;
733        flags.set(DYNAMIC_DATA);
734    }
735
736    /**
737     * get a pointer to the data ptr.
738     */
739    template <typename T>
740    T*
741    getPtr(bool null_ok = false)
742    {
743        assert(null_ok || flags.isSet(STATIC_DATA|DYNAMIC_DATA));
744        return (T*)data;
745    }
746
747    /**
748     * return the value of what is pointed to in the packet.
749     */
750    template <typename T>
751    T get();
752
753    /**
754     * set the value in the data pointer to v.
755     */
756    template <typename T>
757    void set(T v);
758
759    /**
760     * Copy data into the packet from the provided pointer.
761     */
762    void
763    setData(uint8_t *p)
764    {
765        if (p != getPtr<uint8_t>())
766            std::memcpy(getPtr<uint8_t>(), p, getSize());
767    }
768
769    /**
770     * Copy data into the packet from the provided block pointer,
771     * which is aligned to the given block size.
772     */
773    void
774    setDataFromBlock(uint8_t *blk_data, int blkSize)
775    {
776        setData(blk_data + getOffset(blkSize));
777    }
778
779    /**
780     * Copy data from the packet to the provided block pointer, which
781     * is aligned to the given block size.
782     */
783    void
784    writeData(uint8_t *p)
785    {
786        std::memcpy(p, getPtr<uint8_t>(), getSize());
787    }
788
789    /**
790     * Copy data from the packet to the memory at the provided pointer.
791     */
792    void
793    writeDataToBlock(uint8_t *blk_data, int blkSize)
794    {
795        writeData(blk_data + getOffset(blkSize));
796    }
797
798    /**
799     * delete the data pointed to in the data pointer. Ok to call to
800     * matter how data was allocted.
801     */
802    void
803    deleteData()
804    {
805        if (flags.isSet(ARRAY_DATA))
806            delete [] data;
807        else if (flags.isSet(DYNAMIC_DATA))
808            delete data;
809
810        flags.clear(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA);
811        data = NULL;
812    }
813
814    /** If there isn't data in the packet, allocate some. */
815    void
816    allocate()
817    {
818        if (data) {
819            assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
820            return;
821        }
822
823        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
824        flags.set(DYNAMIC_DATA|ARRAY_DATA);
825        data = new uint8_t[getSize()];
826    }
827
828    /**
829     * Check a functional request against a memory value represented
830     * by a base/size pair and an associated data array.  If the
831     * functional request is a read, it may be satisfied by the memory
832     * value.  If the functional request is a write, it may update the
833     * memory value.
834     */
835    bool checkFunctional(Printable *obj, Addr base, int size, uint8_t *data);
836
837    /**
838     * Check a functional request against a memory value stored in
839     * another packet (i.e. an in-transit request or response).
840     */
841    bool
842    checkFunctional(PacketPtr other)
843    {
844        uint8_t *data = other->hasData() ? other->getPtr<uint8_t>() : NULL;
845        return checkFunctional(other, other->getAddr(), other->getSize(),
846                               data);
847    }
848
849    /**
850     * Push label for PrintReq (safe to call unconditionally).
851     */
852    void
853    pushLabel(const std::string &lbl)
854    {
855        if (isPrint())
856            safe_cast<PrintReqState*>(senderState)->pushLabel(lbl);
857    }
858
859    /**
860     * Pop label for PrintReq (safe to call unconditionally).
861     */
862    void
863    popLabel()
864    {
865        if (isPrint())
866            safe_cast<PrintReqState*>(senderState)->popLabel();
867    }
868
869    void print(std::ostream &o, int verbosity = 0,
870               const std::string &prefix = "") const;
871};
872
873#endif //__MEM_PACKET_HH
874