packet.hh revision 9951
111308Santhony.gutierrez@amd.com/*
211308Santhony.gutierrez@amd.com * Copyright (c) 2012-2013 ARM Limited
311308Santhony.gutierrez@amd.com * All rights reserved
411308Santhony.gutierrez@amd.com *
511308Santhony.gutierrez@amd.com * The license below extends only to copyright in the software and shall
611308Santhony.gutierrez@amd.com * not be construed as granting a license to any other intellectual
711308Santhony.gutierrez@amd.com * property including but not limited to intellectual property relating
811308Santhony.gutierrez@amd.com * to a hardware implementation of the functionality of the software
911308Santhony.gutierrez@amd.com * licensed hereunder.  You may use the software subject to the license
1011308Santhony.gutierrez@amd.com * terms below provided that you ensure that this notice is replicated
1111308Santhony.gutierrez@amd.com * unmodified and in its entirety in all distributions of the software,
1211308Santhony.gutierrez@amd.com * modified or unmodified, in source code or in binary form.
1311308Santhony.gutierrez@amd.com *
1411308Santhony.gutierrez@amd.com * Copyright (c) 2006 The Regents of The University of Michigan
1511308Santhony.gutierrez@amd.com * Copyright (c) 2010 Advanced Micro Devices, Inc.
1611308Santhony.gutierrez@amd.com * All rights reserved.
1711308Santhony.gutierrez@amd.com *
1811308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without
1911308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are
2011308Santhony.gutierrez@amd.com * met: redistributions of source code must retain the above copyright
2111308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer;
2211308Santhony.gutierrez@amd.com * redistributions in binary form must reproduce the above copyright
2311308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer in the
2411308Santhony.gutierrez@amd.com * documentation and/or other materials provided with the distribution;
2511308Santhony.gutierrez@amd.com * neither the name of the copyright holders nor the names of its
2611308Santhony.gutierrez@amd.com * contributors may be used to endorse or promote products derived from
2711308Santhony.gutierrez@amd.com * this software without specific prior written permission.
2811308Santhony.gutierrez@amd.com *
2911308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3011308Santhony.gutierrez@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3111308Santhony.gutierrez@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3211308Santhony.gutierrez@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3311308Santhony.gutierrez@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3411308Santhony.gutierrez@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3511534Sjohn.kalamatianos@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3611308Santhony.gutierrez@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3711534Sjohn.kalamatianos@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3811308Santhony.gutierrez@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3911308Santhony.gutierrez@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4011308Santhony.gutierrez@amd.com *
4111308Santhony.gutierrez@amd.com * Authors: Ron Dreslinski
4211308Santhony.gutierrez@amd.com *          Steve Reinhardt
4311308Santhony.gutierrez@amd.com *          Ali Saidi
4411308Santhony.gutierrez@amd.com *          Andreas Hansson
4511308Santhony.gutierrez@amd.com */
4611308Santhony.gutierrez@amd.com
4711308Santhony.gutierrez@amd.com/**
4811308Santhony.gutierrez@amd.com * @file
4911308Santhony.gutierrez@amd.com * Declaration of the Packet class.
5011308Santhony.gutierrez@amd.com */
5111308Santhony.gutierrez@amd.com
5211308Santhony.gutierrez@amd.com#ifndef __MEM_PACKET_HH__
5311308Santhony.gutierrez@amd.com#define __MEM_PACKET_HH__
5411308Santhony.gutierrez@amd.com
5511308Santhony.gutierrez@amd.com#include <bitset>
5611308Santhony.gutierrez@amd.com#include <cassert>
5711308Santhony.gutierrez@amd.com#include <list>
5811308Santhony.gutierrez@amd.com
5911308Santhony.gutierrez@amd.com#include "base/cast.hh"
6011308Santhony.gutierrez@amd.com#include "base/compiler.hh"
6111308Santhony.gutierrez@amd.com#include "base/flags.hh"
6211308Santhony.gutierrez@amd.com#include "base/misc.hh"
6311308Santhony.gutierrez@amd.com#include "base/printable.hh"
6411308Santhony.gutierrez@amd.com#include "base/types.hh"
6511308Santhony.gutierrez@amd.com#include "mem/request.hh"
6611308Santhony.gutierrez@amd.com#include "sim/core.hh"
6711308Santhony.gutierrez@amd.com
6811308Santhony.gutierrez@amd.comclass Packet;
6911308Santhony.gutierrez@amd.comtypedef Packet *PacketPtr;
7011308Santhony.gutierrez@amd.comtypedef uint8_t* PacketDataPtr;
7111308Santhony.gutierrez@amd.comtypedef std::list<PacketPtr> PacketList;
7211308Santhony.gutierrez@amd.com
7311308Santhony.gutierrez@amd.comclass MemCmd
7411308Santhony.gutierrez@amd.com{
7511308Santhony.gutierrez@amd.com    friend class Packet;
7611308Santhony.gutierrez@amd.com
7711308Santhony.gutierrez@amd.com  public:
7811692Santhony.gutierrez@amd.com    /**
7911692Santhony.gutierrez@amd.com     * List of all commands associated with a packet.
8011308Santhony.gutierrez@amd.com     */
8111534Sjohn.kalamatianos@amd.com    enum Command
8211534Sjohn.kalamatianos@amd.com    {
8311534Sjohn.kalamatianos@amd.com        InvalidCmd,
8411534Sjohn.kalamatianos@amd.com        ReadReq,
8511534Sjohn.kalamatianos@amd.com        ReadResp,
8611534Sjohn.kalamatianos@amd.com        ReadRespWithInvalidate,
8711534Sjohn.kalamatianos@amd.com        WriteReq,
8811534Sjohn.kalamatianos@amd.com        WriteResp,
8911534Sjohn.kalamatianos@amd.com        Writeback,
9011534Sjohn.kalamatianos@amd.com        SoftPFReq,
9111534Sjohn.kalamatianos@amd.com        HardPFReq,
9211534Sjohn.kalamatianos@amd.com        SoftPFResp,
9311534Sjohn.kalamatianos@amd.com        HardPFResp,
9411534Sjohn.kalamatianos@amd.com        // WriteInvalidateReq transactions used to be generated by the
9511308Santhony.gutierrez@amd.com        // DMA ports when writing full blocks to memory, however, it
9611308Santhony.gutierrez@amd.com        // is not used anymore since we put the I/O cache in place to
9711534Sjohn.kalamatianos@amd.com        // deal with partial block writes. Hence, WriteInvalidateReq
9811534Sjohn.kalamatianos@amd.com        // and WriteInvalidateResp are currently unused. The
9911534Sjohn.kalamatianos@amd.com        // implication is that the I/O cache does read-exclusive
10011308Santhony.gutierrez@amd.com        // operations on every full-cache-block DMA, and ultimately
10111534Sjohn.kalamatianos@amd.com        // this needs to be fixed.
10211308Santhony.gutierrez@amd.com        WriteInvalidateReq,
10311308Santhony.gutierrez@amd.com        WriteInvalidateResp,
10411308Santhony.gutierrez@amd.com        UpgradeReq,
10511308Santhony.gutierrez@amd.com        SCUpgradeReq,           // Special "weak" upgrade for StoreCond
10611308Santhony.gutierrez@amd.com        UpgradeResp,
10711308Santhony.gutierrez@amd.com        SCUpgradeFailReq,       // Failed SCUpgradeReq in MSHR (never sent)
10811308Santhony.gutierrez@amd.com        UpgradeFailResp,        // Valid for SCUpgradeReq only
10911308Santhony.gutierrez@amd.com        ReadExReq,
11011308Santhony.gutierrez@amd.com        ReadExResp,
11111534Sjohn.kalamatianos@amd.com        LoadLockedReq,
11211308Santhony.gutierrez@amd.com        StoreCondReq,
11311308Santhony.gutierrez@amd.com        StoreCondFailReq,       // Failed StoreCondReq in MSHR (never sent)
11411308Santhony.gutierrez@amd.com        StoreCondResp,
11511308Santhony.gutierrez@amd.com        SwapReq,
11611534Sjohn.kalamatianos@amd.com        SwapResp,
11711308Santhony.gutierrez@amd.com        MessageReq,
11811308Santhony.gutierrez@amd.com        MessageResp,
11911308Santhony.gutierrez@amd.com        // Error responses
12011308Santhony.gutierrez@amd.com        // @TODO these should be classified as responses rather than
12111308Santhony.gutierrez@amd.com        // requests; coding them as requests initially for backwards
12211534Sjohn.kalamatianos@amd.com        // compatibility
12311308Santhony.gutierrez@amd.com        InvalidDestError,  // packet dest field invalid
12411308Santhony.gutierrez@amd.com        BadAddressError,   // memory address invalid
12511534Sjohn.kalamatianos@amd.com        FunctionalReadError, // unable to fulfill functional read
12611308Santhony.gutierrez@amd.com        FunctionalWriteError, // unable to fulfill functional write
12711308Santhony.gutierrez@amd.com        // Fake simulator-only commands
12811534Sjohn.kalamatianos@amd.com        PrintReq,       // Print state matching address
12911308Santhony.gutierrez@amd.com        FlushReq,      //request for a cache flush
13011308Santhony.gutierrez@amd.com        InvalidationReq,   // request for address to be invalidated from lsq
13111308Santhony.gutierrez@amd.com        NUM_MEM_CMDS
13211308Santhony.gutierrez@amd.com    };
13311308Santhony.gutierrez@amd.com
13411308Santhony.gutierrez@amd.com  private:
13511308Santhony.gutierrez@amd.com    /**
13611308Santhony.gutierrez@amd.com     * List of command attributes.
13711308Santhony.gutierrez@amd.com     */
13811308Santhony.gutierrez@amd.com    enum Attribute
13911308Santhony.gutierrez@amd.com    {
14011534Sjohn.kalamatianos@amd.com        IsRead,         //!< Data flows from responder to requester
14111308Santhony.gutierrez@amd.com        IsWrite,        //!< Data flows from requester to responder
14211308Santhony.gutierrez@amd.com        IsUpgrade,
14311534Sjohn.kalamatianos@amd.com        IsInvalidate,
14411308Santhony.gutierrez@amd.com        NeedsExclusive, //!< Requires exclusive copy to complete in-cache
14511308Santhony.gutierrez@amd.com        IsRequest,      //!< Issued by requester
14611308Santhony.gutierrez@amd.com        IsResponse,     //!< Issue by responder
14711308Santhony.gutierrez@amd.com        NeedsResponse,  //!< Requester needs response from target
14811308Santhony.gutierrez@amd.com        IsSWPrefetch,
14911308Santhony.gutierrez@amd.com        IsHWPrefetch,
15011308Santhony.gutierrez@amd.com        IsLlsc,         //!< Alpha/MIPS LL or SC access
15111308Santhony.gutierrez@amd.com        HasData,        //!< There is an associated payload
15211308Santhony.gutierrez@amd.com        IsError,        //!< Error response
15311308Santhony.gutierrez@amd.com        IsPrint,        //!< Print state matching address (for debugging)
15411308Santhony.gutierrez@amd.com        IsFlush,        //!< Flush the address from caches
15511308Santhony.gutierrez@amd.com        NUM_COMMAND_ATTRIBUTES
15611308Santhony.gutierrez@amd.com    };
15711308Santhony.gutierrez@amd.com
15811308Santhony.gutierrez@amd.com    /**
15911308Santhony.gutierrez@amd.com     * Structure that defines attributes and other data associated
16011308Santhony.gutierrez@amd.com     * with a Command.
16111308Santhony.gutierrez@amd.com     */
16211534Sjohn.kalamatianos@amd.com    struct CommandInfo
16311308Santhony.gutierrez@amd.com    {
16411308Santhony.gutierrez@amd.com        /// Set of attribute flags.
16511308Santhony.gutierrez@amd.com        const std::bitset<NUM_COMMAND_ATTRIBUTES> attributes;
16611534Sjohn.kalamatianos@amd.com        /// Corresponding response for requests; InvalidCmd if no
16711534Sjohn.kalamatianos@amd.com        /// response is applicable.
16811534Sjohn.kalamatianos@amd.com        const Command response;
16911308Santhony.gutierrez@amd.com        /// String representation (for printing)
17011308Santhony.gutierrez@amd.com        const std::string str;
17111308Santhony.gutierrez@amd.com    };
17211308Santhony.gutierrez@amd.com
17311308Santhony.gutierrez@amd.com    /// Array to map Command enum to associated info.
17411308Santhony.gutierrez@amd.com    static const CommandInfo commandInfo[];
17511308Santhony.gutierrez@amd.com
17611308Santhony.gutierrez@amd.com  private:
17711308Santhony.gutierrez@amd.com
17811657Salexandru.dutu@amd.com    Command cmd;
17911308Santhony.gutierrez@amd.com
18011308Santhony.gutierrez@amd.com    bool
18111308Santhony.gutierrez@amd.com    testCmdAttrib(MemCmd::Attribute attrib) const
18211639Salexandru.dutu@amd.com    {
18311639Salexandru.dutu@amd.com        return commandInfo[cmd].attributes[attrib] != 0;
18411639Salexandru.dutu@amd.com    }
18511639Salexandru.dutu@amd.com
18611639Salexandru.dutu@amd.com  public:
18711639Salexandru.dutu@amd.com
18811639Salexandru.dutu@amd.com    bool isRead() const         { return testCmdAttrib(IsRead); }
18911308Santhony.gutierrez@amd.com    bool isWrite() const        { return testCmdAttrib(IsWrite); }
19011308Santhony.gutierrez@amd.com    bool isUpgrade() const      { return testCmdAttrib(IsUpgrade); }
19111308Santhony.gutierrez@amd.com    bool isRequest() const      { return testCmdAttrib(IsRequest); }
19211308Santhony.gutierrez@amd.com    bool isResponse() const     { return testCmdAttrib(IsResponse); }
19311308Santhony.gutierrez@amd.com    bool needsExclusive() const { return testCmdAttrib(NeedsExclusive); }
19411657Salexandru.dutu@amd.com    bool needsResponse() const  { return testCmdAttrib(NeedsResponse); }
19511308Santhony.gutierrez@amd.com    bool isInvalidate() const   { return testCmdAttrib(IsInvalidate); }
19611308Santhony.gutierrez@amd.com    bool hasData() const        { return testCmdAttrib(HasData); }
19711308Santhony.gutierrez@amd.com    bool isReadWrite() const    { return isRead() && isWrite(); }
19811308Santhony.gutierrez@amd.com    bool isLLSC() const         { return testCmdAttrib(IsLlsc); }
19911308Santhony.gutierrez@amd.com    bool isError() const        { return testCmdAttrib(IsError); }
20011308Santhony.gutierrez@amd.com    bool isPrint() const        { return testCmdAttrib(IsPrint); }
20111308Santhony.gutierrez@amd.com    bool isFlush() const        { return testCmdAttrib(IsFlush); }
20211308Santhony.gutierrez@amd.com
20311308Santhony.gutierrez@amd.com    const Command
20411308Santhony.gutierrez@amd.com    responseCommand() const
20511308Santhony.gutierrez@amd.com    {
20611308Santhony.gutierrez@amd.com        return commandInfo[cmd].response;
20711308Santhony.gutierrez@amd.com    }
20811308Santhony.gutierrez@amd.com
20911308Santhony.gutierrez@amd.com    /// Return the string to a cmd given by idx.
21011308Santhony.gutierrez@amd.com    const std::string &toString() const { return commandInfo[cmd].str; }
21111308Santhony.gutierrez@amd.com    int toInt() const { return (int)cmd; }
21211308Santhony.gutierrez@amd.com
21311308Santhony.gutierrez@amd.com    MemCmd(Command _cmd) : cmd(_cmd) { }
21411308Santhony.gutierrez@amd.com    MemCmd(int _cmd) : cmd((Command)_cmd) { }
21511308Santhony.gutierrez@amd.com    MemCmd() : cmd(InvalidCmd) { }
21611308Santhony.gutierrez@amd.com
21711308Santhony.gutierrez@amd.com    bool operator==(MemCmd c2) const { return (cmd == c2.cmd); }
21811308Santhony.gutierrez@amd.com    bool operator!=(MemCmd c2) const { return (cmd != c2.cmd); }
21911308Santhony.gutierrez@amd.com};
22011308Santhony.gutierrez@amd.com
22111308Santhony.gutierrez@amd.com/**
22211308Santhony.gutierrez@amd.com * A Packet is used to encapsulate a transfer between two objects in
22311308Santhony.gutierrez@amd.com * the memory system (e.g., the L1 and L2 cache).  (In contrast, a
22411308Santhony.gutierrez@amd.com * single Request travels all the way from the requester to the
22511657Salexandru.dutu@amd.com * ultimate destination and back, possibly being conveyed by several
22611657Salexandru.dutu@amd.com * different Packets along the way.)
22711308Santhony.gutierrez@amd.com */
22811308Santhony.gutierrez@amd.comclass Packet : public Printable
22911308Santhony.gutierrez@amd.com{
23011638Salexandru.dutu@amd.com  public:
23111638Salexandru.dutu@amd.com    typedef uint32_t FlagsType;
23211638Salexandru.dutu@amd.com    typedef ::Flags<FlagsType> Flags;
23311638Salexandru.dutu@amd.com
23411657Salexandru.dutu@amd.com  private:
23511638Salexandru.dutu@amd.com    static const FlagsType PUBLIC_FLAGS           = 0x00000000;
23611638Salexandru.dutu@amd.com    static const FlagsType PRIVATE_FLAGS          = 0x00007F0F;
23711638Salexandru.dutu@amd.com    static const FlagsType COPY_FLAGS             = 0x0000000F;
23811639Salexandru.dutu@amd.com
23911643Salexandru.dutu@amd.com    static const FlagsType SHARED                 = 0x00000001;
24011639Salexandru.dutu@amd.com    // Special control flags
24111308Santhony.gutierrez@amd.com    /// Special timing-mode atomic snoop for multi-level coherence.
24211534Sjohn.kalamatianos@amd.com    static const FlagsType EXPRESS_SNOOP          = 0x00000002;
24311657Salexandru.dutu@amd.com    /// Does supplier have exclusive copy?
24411657Salexandru.dutu@amd.com    /// Useful for multi-level coherence.
24511657Salexandru.dutu@amd.com    static const FlagsType SUPPLY_EXCLUSIVE       = 0x00000004;
24611657Salexandru.dutu@amd.com    // Snoop response flags
24711657Salexandru.dutu@amd.com    static const FlagsType MEM_INHIBIT            = 0x00000008;
24811308Santhony.gutierrez@amd.com    /// Are the 'addr' and 'size' fields valid?
24911657Salexandru.dutu@amd.com    static const FlagsType VALID_ADDR             = 0x00000100;
25011657Salexandru.dutu@amd.com    static const FlagsType VALID_SIZE             = 0x00000200;
25111639Salexandru.dutu@amd.com    /// Is the data pointer set to a value that shouldn't be freed
25211308Santhony.gutierrez@amd.com    /// when the packet is destroyed?
25311308Santhony.gutierrez@amd.com    static const FlagsType STATIC_DATA            = 0x00001000;
25411657Salexandru.dutu@amd.com    /// The data pointer points to a value that should be freed when
25511308Santhony.gutierrez@amd.com    /// the packet is destroyed.
25611639Salexandru.dutu@amd.com    static const FlagsType DYNAMIC_DATA           = 0x00002000;
25711308Santhony.gutierrez@amd.com    /// the data pointer points to an array (thus delete []) needs to
25811639Salexandru.dutu@amd.com    /// be called on it rather than simply delete.
25911639Salexandru.dutu@amd.com    static const FlagsType ARRAY_DATA             = 0x00004000;
26011639Salexandru.dutu@amd.com    /// suppress the error if this packet encounters a functional
26111308Santhony.gutierrez@amd.com    /// access failure.
26211638Salexandru.dutu@amd.com    static const FlagsType SUPPRESS_FUNC_ERROR    = 0x00008000;
26311638Salexandru.dutu@amd.com
26411638Salexandru.dutu@amd.com    Flags flags;
26511638Salexandru.dutu@amd.com
26611638Salexandru.dutu@amd.com  public:
26711638Salexandru.dutu@amd.com    typedef MemCmd::Command Command;
26811638Salexandru.dutu@amd.com
26911308Santhony.gutierrez@amd.com    /// The command field of the packet.
27011308Santhony.gutierrez@amd.com    MemCmd cmd;
27111639Salexandru.dutu@amd.com
27211639Salexandru.dutu@amd.com    /// A pointer to the original request.
27311639Salexandru.dutu@amd.com    RequestPtr req;
27411639Salexandru.dutu@amd.com
27511639Salexandru.dutu@amd.com  private:
27611308Santhony.gutierrez@amd.com   /**
27711639Salexandru.dutu@amd.com    * A pointer to the data being transfered.  It can be differnt
27811308Santhony.gutierrez@amd.com    * sizes at each level of the heirarchy so it belongs in the
27911308Santhony.gutierrez@amd.com    * packet, not request. This may or may not be populated when a
28011638Salexandru.dutu@amd.com    * responder recieves the packet. If not populated it memory should
28111638Salexandru.dutu@amd.com    * be allocated.
28211308Santhony.gutierrez@amd.com    */
28311308Santhony.gutierrez@amd.com    PacketDataPtr data;
28411639Salexandru.dutu@amd.com
28511308Santhony.gutierrez@amd.com    /// The address of the request.  This address could be virtual or
28611639Salexandru.dutu@amd.com    /// physical, depending on the system configuration.
28711308Santhony.gutierrez@amd.com    Addr addr;
28811308Santhony.gutierrez@amd.com
28911308Santhony.gutierrez@amd.com    /// The size of the request or transfer.
29011308Santhony.gutierrez@amd.com    unsigned size;
29111308Santhony.gutierrez@amd.com
29211308Santhony.gutierrez@amd.com    /**
29311308Santhony.gutierrez@amd.com     * Source port identifier set on a request packet to enable
29411308Santhony.gutierrez@amd.com     * appropriate routing of the responses. The source port
29511308Santhony.gutierrez@amd.com     * identifier is set by any multiplexing component, e.g. a bus, as
29611657Salexandru.dutu@amd.com     * the timing responses need this information to be routed back to
29711657Salexandru.dutu@amd.com     * the appropriate port at a later point in time. The field can be
29811308Santhony.gutierrez@amd.com     * updated (over-written) as the request packet passes through
29911534Sjohn.kalamatianos@amd.com     * additional multiplexing components, and it is their
30011308Santhony.gutierrez@amd.com     * responsibility to remember the original source port identifier,
30111308Santhony.gutierrez@amd.com     * for example by using an appropriate sender state. The latter is
30211308Santhony.gutierrez@amd.com     * done in the cache and bridge.
30311308Santhony.gutierrez@amd.com     */
30411308Santhony.gutierrez@amd.com    PortID src;
30511308Santhony.gutierrez@amd.com
30611308Santhony.gutierrez@amd.com    /**
30711308Santhony.gutierrez@amd.com     * Destination port identifier that is present on all response
30811308Santhony.gutierrez@amd.com     * packets that passed through a multiplexing component as a
30911308Santhony.gutierrez@amd.com     * request packet. The source port identifier is turned into a
31011308Santhony.gutierrez@amd.com     * destination port identifier when the packet is turned into a
31111308Santhony.gutierrez@amd.com     * response, and the destination is used, e.g. by the bus, to
31211308Santhony.gutierrez@amd.com     * select the appropriate path through the interconnect.
31311308Santhony.gutierrez@amd.com     */
31411308Santhony.gutierrez@amd.com    PortID dest;
31511308Santhony.gutierrez@amd.com
31611308Santhony.gutierrez@amd.com    /**
31711308Santhony.gutierrez@amd.com     * The original value of the command field.  Only valid when the
31811308Santhony.gutierrez@amd.com     * current command field is an error condition; in that case, the
31911308Santhony.gutierrez@amd.com     * previous contents of the command field are copied here.  This
32011692Santhony.gutierrez@amd.com     * field is *not* set on non-error responses.
32111692Santhony.gutierrez@amd.com     */
32211692Santhony.gutierrez@amd.com    MemCmd origCmd;
32311308Santhony.gutierrez@amd.com
32411308Santhony.gutierrez@amd.com    /**
32511308Santhony.gutierrez@amd.com     * These values specify the range of bytes found that satisfy a
32611308Santhony.gutierrez@amd.com     * functional read.
32711308Santhony.gutierrez@amd.com     */
32811308Santhony.gutierrez@amd.com    uint16_t bytesValidStart;
32911308Santhony.gutierrez@amd.com    uint16_t bytesValidEnd;
33011643Salexandru.dutu@amd.com
33111308Santhony.gutierrez@amd.com  public:
33211308Santhony.gutierrez@amd.com
33311308Santhony.gutierrez@amd.com    /**
33411308Santhony.gutierrez@amd.com     * The extra delay from seeing the packet until the first word is
33511308Santhony.gutierrez@amd.com     * transmitted by the bus that provided it (if any). This delay is
33611308Santhony.gutierrez@amd.com     * used to communicate the bus waiting time to the neighbouring
33711308Santhony.gutierrez@amd.com     * object (e.g. a cache) that actually makes the packet wait. As
33811308Santhony.gutierrez@amd.com     * the delay is relative, a 32-bit unsigned should be sufficient.
33911657Salexandru.dutu@amd.com     */
34011308Santhony.gutierrez@amd.com    uint32_t busFirstWordDelay;
34111308Santhony.gutierrez@amd.com
34211657Salexandru.dutu@amd.com    /**
34311308Santhony.gutierrez@amd.com     * The extra delay from seeing the packet until the last word is
34411308Santhony.gutierrez@amd.com     * transmitted by the bus that provided it (if any). Similar to
34511308Santhony.gutierrez@amd.com     * the first word time, this is used to make up for the fact that
34611308Santhony.gutierrez@amd.com     * the bus does not make the packet wait. As the delay is relative,
34711308Santhony.gutierrez@amd.com     * a 32-bit unsigned should be sufficient.
34811308Santhony.gutierrez@amd.com     */
34911308Santhony.gutierrez@amd.com    uint32_t busLastWordDelay;
35011308Santhony.gutierrez@amd.com
35111308Santhony.gutierrez@amd.com    /**
35211308Santhony.gutierrez@amd.com     * A virtual base opaque structure used to hold state associated
35311308Santhony.gutierrez@amd.com     * with the packet (e.g., an MSHR), specific to a MemObject that
35411308Santhony.gutierrez@amd.com     * sees the packet. A pointer to this state is returned in the
35511657Salexandru.dutu@amd.com     * packet's response so that the MemObject in question can quickly
35611643Salexandru.dutu@amd.com     * look up the state needed to process it. A specific subclass
35711308Santhony.gutierrez@amd.com     * would be derived from this to carry state specific to a
35811308Santhony.gutierrez@amd.com     * particular sending device.
35911308Santhony.gutierrez@amd.com     *
36011308Santhony.gutierrez@amd.com     * As multiple MemObjects may add their SenderState throughout the
36111308Santhony.gutierrez@amd.com     * memory system, the SenderStates create a stack, where a
36211308Santhony.gutierrez@amd.com     * MemObject can add a new Senderstate, as long as the
36311308Santhony.gutierrez@amd.com     * predecessing SenderState is restored when the response comes
36411308Santhony.gutierrez@amd.com     * back. For this reason, the predecessor should always be
36511308Santhony.gutierrez@amd.com     * populated with the current SenderState of a packet before
36611308Santhony.gutierrez@amd.com     * modifying the senderState field in the request packet.
36711308Santhony.gutierrez@amd.com     */
36811308Santhony.gutierrez@amd.com    struct SenderState
36911308Santhony.gutierrez@amd.com    {
37011308Santhony.gutierrez@amd.com        SenderState* predecessor;
37111308Santhony.gutierrez@amd.com        SenderState() : predecessor(NULL) {}
37211308Santhony.gutierrez@amd.com        virtual ~SenderState() {}
37311308Santhony.gutierrez@amd.com    };
37411308Santhony.gutierrez@amd.com
37511308Santhony.gutierrez@amd.com    /**
37611308Santhony.gutierrez@amd.com     * Object used to maintain state of a PrintReq.  The senderState
37711308Santhony.gutierrez@amd.com     * field of a PrintReq should always be of this type.
37811308Santhony.gutierrez@amd.com     */
37911308Santhony.gutierrez@amd.com    class PrintReqState : public SenderState
38011308Santhony.gutierrez@amd.com    {
38111308Santhony.gutierrez@amd.com      private:
38211308Santhony.gutierrez@amd.com        /**
38311534Sjohn.kalamatianos@amd.com         * An entry in the label stack.
38411308Santhony.gutierrez@amd.com         */
38511308Santhony.gutierrez@amd.com        struct LabelStackEntry
38611308Santhony.gutierrez@amd.com        {
38711308Santhony.gutierrez@amd.com            const std::string label;
38811308Santhony.gutierrez@amd.com            std::string *prefix;
38911308Santhony.gutierrez@amd.com            bool labelPrinted;
39011308Santhony.gutierrez@amd.com            LabelStackEntry(const std::string &_label, std::string *_prefix);
39111308Santhony.gutierrez@amd.com        };
39211308Santhony.gutierrez@amd.com
39311308Santhony.gutierrez@amd.com        typedef std::list<LabelStackEntry> LabelStack;
39411308Santhony.gutierrez@amd.com        LabelStack labelStack;
39511308Santhony.gutierrez@amd.com
39611308Santhony.gutierrez@amd.com        std::string *curPrefixPtr;
39711308Santhony.gutierrez@amd.com
39811308Santhony.gutierrez@amd.com      public:
39911308Santhony.gutierrez@amd.com        std::ostream &os;
40011308Santhony.gutierrez@amd.com        const int verbosity;
40111308Santhony.gutierrez@amd.com
40211308Santhony.gutierrez@amd.com        PrintReqState(std::ostream &os, int verbosity = 0);
40311308Santhony.gutierrez@amd.com        ~PrintReqState();
40411308Santhony.gutierrez@amd.com
40511308Santhony.gutierrez@amd.com        /**
40611308Santhony.gutierrez@amd.com         * Returns the current line prefix.
40711308Santhony.gutierrez@amd.com         */
40811308Santhony.gutierrez@amd.com        const std::string &curPrefix() { return *curPrefixPtr; }
40911308Santhony.gutierrez@amd.com
41011308Santhony.gutierrez@amd.com        /**
41111308Santhony.gutierrez@amd.com         * Push a label onto the label stack, and prepend the given
41211308Santhony.gutierrez@amd.com         * prefix string onto the current prefix.  Labels will only be
41311308Santhony.gutierrez@amd.com         * printed if an object within the label's scope is printed.
41411308Santhony.gutierrez@amd.com         */
41511308Santhony.gutierrez@amd.com        void pushLabel(const std::string &lbl,
41611308Santhony.gutierrez@amd.com                       const std::string &prefix = "  ");
41711308Santhony.gutierrez@amd.com
41811308Santhony.gutierrez@amd.com        /**
41911308Santhony.gutierrez@amd.com         * Pop a label off the label stack.
42011308Santhony.gutierrez@amd.com         */
42111308Santhony.gutierrez@amd.com        void popLabel();
42211308Santhony.gutierrez@amd.com
42311308Santhony.gutierrez@amd.com        /**
42411308Santhony.gutierrez@amd.com         * Print all of the pending unprinted labels on the
42511308Santhony.gutierrez@amd.com         * stack. Called by printObj(), so normally not called by
42611308Santhony.gutierrez@amd.com         * users unless bypassing printObj().
42711308Santhony.gutierrez@amd.com         */
42811308Santhony.gutierrez@amd.com        void printLabels();
42911308Santhony.gutierrez@amd.com
43011308Santhony.gutierrez@amd.com        /**
43111308Santhony.gutierrez@amd.com         * Print a Printable object to os, because it matched the
43211308Santhony.gutierrez@amd.com         * address on a PrintReq.
43311308Santhony.gutierrez@amd.com         */
43411308Santhony.gutierrez@amd.com        void printObj(Printable *obj);
43511308Santhony.gutierrez@amd.com    };
43611308Santhony.gutierrez@amd.com
43711308Santhony.gutierrez@amd.com    /**
43811308Santhony.gutierrez@amd.com     * This packet's sender state.  Devices should use dynamic_cast<>
43911308Santhony.gutierrez@amd.com     * to cast to the state appropriate to the sender.  The intent of
44011308Santhony.gutierrez@amd.com     * this variable is to allow a device to attach extra information
44111308Santhony.gutierrez@amd.com     * to a request. A response packet must return the sender state
44211308Santhony.gutierrez@amd.com     * that was attached to the original request (even if a new packet
44311308Santhony.gutierrez@amd.com     * is created).
44411308Santhony.gutierrez@amd.com     */
44511308Santhony.gutierrez@amd.com    SenderState *senderState;
44611308Santhony.gutierrez@amd.com
44711308Santhony.gutierrez@amd.com    /**
44811308Santhony.gutierrez@amd.com     * Push a new sender state to the packet and make the current
44911308Santhony.gutierrez@amd.com     * sender state the predecessor of the new one. This should be
45011308Santhony.gutierrez@amd.com     * prefered over direct manipulation of the senderState member
45111308Santhony.gutierrez@amd.com     * variable.
45211308Santhony.gutierrez@amd.com     *
45311308Santhony.gutierrez@amd.com     * @param sender_state SenderState to push at the top of the stack
45411308Santhony.gutierrez@amd.com     */
45511308Santhony.gutierrez@amd.com    void pushSenderState(SenderState *sender_state);
45611308Santhony.gutierrez@amd.com
45711308Santhony.gutierrez@amd.com    /**
45811639Salexandru.dutu@amd.com     * Pop the top of the state stack and return a pointer to it. This
45911308Santhony.gutierrez@amd.com     * assumes the current sender state is not NULL. This should be
46011308Santhony.gutierrez@amd.com     * preferred over direct manipulation of the senderState member
46111639Salexandru.dutu@amd.com     * variable.
46211308Santhony.gutierrez@amd.com     *
46311308Santhony.gutierrez@amd.com     * @return The current top of the stack
46411308Santhony.gutierrez@amd.com     */
46511639Salexandru.dutu@amd.com    SenderState *popSenderState();
46611639Salexandru.dutu@amd.com
46711308Santhony.gutierrez@amd.com    /**
46811308Santhony.gutierrez@amd.com     * Go through the sender state stack and return the first instance
46911308Santhony.gutierrez@amd.com     * that is of type T (as determined by a dynamic_cast). If there
47011308Santhony.gutierrez@amd.com     * is no sender state of type T, NULL is returned.
47111308Santhony.gutierrez@amd.com     *
47211308Santhony.gutierrez@amd.com     * @return The topmost state of type T
47311308Santhony.gutierrez@amd.com     */
47411308Santhony.gutierrez@amd.com    template <typename T>
47511308Santhony.gutierrez@amd.com    T * findNextSenderState() const
47611308Santhony.gutierrez@amd.com    {
47711308Santhony.gutierrez@amd.com        T *t = NULL;
47811308Santhony.gutierrez@amd.com        SenderState* sender_state = senderState;
47911308Santhony.gutierrez@amd.com        while (t == NULL && sender_state != NULL) {
48011308Santhony.gutierrez@amd.com            t = dynamic_cast<T*>(sender_state);
48111308Santhony.gutierrez@amd.com            sender_state = sender_state->predecessor;
48211308Santhony.gutierrez@amd.com        }
48311308Santhony.gutierrez@amd.com        return t;
48411308Santhony.gutierrez@amd.com    }
48511308Santhony.gutierrez@amd.com
48611308Santhony.gutierrez@amd.com    /// Return the string name of the cmd field (for debugging and
48711308Santhony.gutierrez@amd.com    /// tracing).
48811308Santhony.gutierrez@amd.com    const std::string &cmdString() const { return cmd.toString(); }
48911308Santhony.gutierrez@amd.com
49011308Santhony.gutierrez@amd.com    /// Return the index of this command.
49111308Santhony.gutierrez@amd.com    inline int cmdToIndex() const { return cmd.toInt(); }
49211308Santhony.gutierrez@amd.com
49311308Santhony.gutierrez@amd.com    bool isRead() const         { return cmd.isRead(); }
49411308Santhony.gutierrez@amd.com    bool isWrite() const        { return cmd.isWrite(); }
49511308Santhony.gutierrez@amd.com    bool isUpgrade()  const     { return cmd.isUpgrade(); }
49611308Santhony.gutierrez@amd.com    bool isRequest() const      { return cmd.isRequest(); }
49711308Santhony.gutierrez@amd.com    bool isResponse() const     { return cmd.isResponse(); }
49811308Santhony.gutierrez@amd.com    bool needsExclusive() const { return cmd.needsExclusive(); }
49911308Santhony.gutierrez@amd.com    bool needsResponse() const  { return cmd.needsResponse(); }
50011308Santhony.gutierrez@amd.com    bool isInvalidate() const   { return cmd.isInvalidate(); }
50111308Santhony.gutierrez@amd.com    bool hasData() const        { return cmd.hasData(); }
50211308Santhony.gutierrez@amd.com    bool isReadWrite() const    { return cmd.isReadWrite(); }
50311308Santhony.gutierrez@amd.com    bool isLLSC() const         { return cmd.isLLSC(); }
50411308Santhony.gutierrez@amd.com    bool isError() const        { return cmd.isError(); }
50511308Santhony.gutierrez@amd.com    bool isPrint() const        { return cmd.isPrint(); }
50611308Santhony.gutierrez@amd.com    bool isFlush() const        { return cmd.isFlush(); }
50711308Santhony.gutierrez@amd.com
50811308Santhony.gutierrez@amd.com    // Snoop flags
50911308Santhony.gutierrez@amd.com    void assertMemInhibit()         { flags.set(MEM_INHIBIT); }
51011308Santhony.gutierrez@amd.com    bool memInhibitAsserted() const { return flags.isSet(MEM_INHIBIT); }
51111308Santhony.gutierrez@amd.com    void assertShared()             { flags.set(SHARED); }
51211308Santhony.gutierrez@amd.com    bool sharedAsserted() const     { return flags.isSet(SHARED); }
51311308Santhony.gutierrez@amd.com
51411308Santhony.gutierrez@amd.com    // Special control flags
51511308Santhony.gutierrez@amd.com    void setExpressSnoop()          { flags.set(EXPRESS_SNOOP); }
51611308Santhony.gutierrez@amd.com    bool isExpressSnoop() const     { return flags.isSet(EXPRESS_SNOOP); }
51711308Santhony.gutierrez@amd.com    void setSupplyExclusive()       { flags.set(SUPPLY_EXCLUSIVE); }
51811308Santhony.gutierrez@amd.com    void clearSupplyExclusive()     { flags.clear(SUPPLY_EXCLUSIVE); }
51911308Santhony.gutierrez@amd.com    bool isSupplyExclusive() const  { return flags.isSet(SUPPLY_EXCLUSIVE); }
52011308Santhony.gutierrez@amd.com    void setSuppressFuncError()     { flags.set(SUPPRESS_FUNC_ERROR); }
52111308Santhony.gutierrez@amd.com    bool suppressFuncError() const  { return flags.isSet(SUPPRESS_FUNC_ERROR); }
52211308Santhony.gutierrez@amd.com
52311308Santhony.gutierrez@amd.com    // Network error conditions... encapsulate them as methods since
52411308Santhony.gutierrez@amd.com    // their encoding keeps changing (from result field to command
52511308Santhony.gutierrez@amd.com    // field, etc.)
52611308Santhony.gutierrez@amd.com    void
52711308Santhony.gutierrez@amd.com    setBadAddress()
52811308Santhony.gutierrez@amd.com    {
52911308Santhony.gutierrez@amd.com        assert(isResponse());
53011308Santhony.gutierrez@amd.com        cmd = MemCmd::BadAddressError;
53111308Santhony.gutierrez@amd.com    }
53211308Santhony.gutierrez@amd.com
53311308Santhony.gutierrez@amd.com    bool hadBadAddress() const { return cmd == MemCmd::BadAddressError; }
53411308Santhony.gutierrez@amd.com    void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; }
53511308Santhony.gutierrez@amd.com
53611308Santhony.gutierrez@amd.com    bool isSrcValid() const { return src != InvalidPortID; }
53711308Santhony.gutierrez@amd.com    /// Accessor function to get the source index of the packet.
53811308Santhony.gutierrez@amd.com    PortID getSrc() const { assert(isSrcValid()); return src; }
53911308Santhony.gutierrez@amd.com    /// Accessor function to set the source index of the packet.
54011308Santhony.gutierrez@amd.com    void setSrc(PortID _src) { src = _src; }
54111308Santhony.gutierrez@amd.com    /// Reset source field, e.g. to retransmit packet on different bus.
54211308Santhony.gutierrez@amd.com    void clearSrc() { src = InvalidPortID; }
54311308Santhony.gutierrez@amd.com
54411308Santhony.gutierrez@amd.com    bool isDestValid() const { return dest != InvalidPortID; }
54511308Santhony.gutierrez@amd.com    /// Accessor function for the destination index of the packet.
54611308Santhony.gutierrez@amd.com    PortID getDest() const { assert(isDestValid()); return dest; }
54711308Santhony.gutierrez@amd.com    /// Accessor function to set the destination index of the packet.
54811308Santhony.gutierrez@amd.com    void setDest(PortID _dest) { dest = _dest; }
54911308Santhony.gutierrez@amd.com    /// Reset destination field, e.g. to turn a response into a request again.
55011345Sjohn.kalamatianos@amd.com    void clearDest() { dest = InvalidPortID; }
55111345Sjohn.kalamatianos@amd.com
55211308Santhony.gutierrez@amd.com    Addr getAddr() const { assert(flags.isSet(VALID_ADDR)); return addr; }
55311308Santhony.gutierrez@amd.com    /**
55411308Santhony.gutierrez@amd.com     * Update the address of this packet mid-transaction. This is used
55511308Santhony.gutierrez@amd.com     * by the address mapper to change an already set address to a new
55611308Santhony.gutierrez@amd.com     * one based on the system configuration. It is intended to remap
55711308Santhony.gutierrez@amd.com     * an existing address, so it asserts that the current address is
55811308Santhony.gutierrez@amd.com     * valid.
55911345Sjohn.kalamatianos@amd.com     */
56011308Santhony.gutierrez@amd.com    void setAddr(Addr _addr) { assert(flags.isSet(VALID_ADDR)); addr = _addr; }
56111308Santhony.gutierrez@amd.com
56211308Santhony.gutierrez@amd.com    unsigned getSize() const  { assert(flags.isSet(VALID_SIZE)); return size; }
56311308Santhony.gutierrez@amd.com    Addr getOffset(int blkSize) const { return getAddr() & (Addr)(blkSize - 1); }
56411308Santhony.gutierrez@amd.com
56511308Santhony.gutierrez@amd.com    /**
56611308Santhony.gutierrez@amd.com     * It has been determined that the SC packet should successfully update
56711345Sjohn.kalamatianos@amd.com     * memory.  Therefore, convert this SC packet to a normal write.
56811308Santhony.gutierrez@amd.com     */
56911308Santhony.gutierrez@amd.com    void
57011308Santhony.gutierrez@amd.com    convertScToWrite()
57111308Santhony.gutierrez@amd.com    {
57211308Santhony.gutierrez@amd.com        assert(isLLSC());
57311308Santhony.gutierrez@amd.com        assert(isWrite());
57411308Santhony.gutierrez@amd.com        cmd = MemCmd::WriteReq;
57511345Sjohn.kalamatianos@amd.com    }
57611308Santhony.gutierrez@amd.com
57711308Santhony.gutierrez@amd.com    /**
57811308Santhony.gutierrez@amd.com     * When ruby is in use, Ruby will monitor the cache line and thus M5
57911308Santhony.gutierrez@amd.com     * phys memory should treat LL ops as normal reads.
58011345Sjohn.kalamatianos@amd.com     */
58111308Santhony.gutierrez@amd.com    void
58211308Santhony.gutierrez@amd.com    convertLlToRead()
58311308Santhony.gutierrez@amd.com    {
58411308Santhony.gutierrez@amd.com        assert(isLLSC());
58511308Santhony.gutierrez@amd.com        assert(isRead());
58611534Sjohn.kalamatianos@amd.com        cmd = MemCmd::ReadReq;
58711308Santhony.gutierrez@amd.com    }
58811308Santhony.gutierrez@amd.com
58911308Santhony.gutierrez@amd.com    /**
59011308Santhony.gutierrez@amd.com     * Constructor.  Note that a Request object must be constructed
59111308Santhony.gutierrez@amd.com     * first, but the Requests's physical address and size fields need
59211308Santhony.gutierrez@amd.com     * not be valid. The command must be supplied.
59311308Santhony.gutierrez@amd.com     */
59411308Santhony.gutierrez@amd.com    Packet(Request *_req, MemCmd _cmd)
59511308Santhony.gutierrez@amd.com        :  cmd(_cmd), req(_req), data(NULL),
59611308Santhony.gutierrez@amd.com           src(InvalidPortID), dest(InvalidPortID),
59711308Santhony.gutierrez@amd.com           bytesValidStart(0), bytesValidEnd(0),
59811308Santhony.gutierrez@amd.com           busFirstWordDelay(0), busLastWordDelay(0),
59911308Santhony.gutierrez@amd.com           senderState(NULL)
60011308Santhony.gutierrez@amd.com    {
60111308Santhony.gutierrez@amd.com        if (req->hasPaddr()) {
60211308Santhony.gutierrez@amd.com            addr = req->getPaddr();
60311308Santhony.gutierrez@amd.com            flags.set(VALID_ADDR);
60411308Santhony.gutierrez@amd.com        }
60511308Santhony.gutierrez@amd.com        if (req->hasSize()) {
60611308Santhony.gutierrez@amd.com            size = req->getSize();
60711308Santhony.gutierrez@amd.com            flags.set(VALID_SIZE);
60811308Santhony.gutierrez@amd.com        }
60911308Santhony.gutierrez@amd.com    }
61011308Santhony.gutierrez@amd.com
61111308Santhony.gutierrez@amd.com    /**
61211308Santhony.gutierrez@amd.com     * Alternate constructor if you are trying to create a packet with
61311308Santhony.gutierrez@amd.com     * a request that is for a whole block, not the address from the
61411308Santhony.gutierrez@amd.com     * req.  this allows for overriding the size/addr of the req.
61511308Santhony.gutierrez@amd.com     */
61611308Santhony.gutierrez@amd.com    Packet(Request *_req, MemCmd _cmd, int _blkSize)
61711308Santhony.gutierrez@amd.com        :  cmd(_cmd), req(_req), data(NULL),
61811308Santhony.gutierrez@amd.com           src(InvalidPortID), dest(InvalidPortID),
61911308Santhony.gutierrez@amd.com           bytesValidStart(0), bytesValidEnd(0),
62011308Santhony.gutierrez@amd.com           busFirstWordDelay(0), busLastWordDelay(0),
62111308Santhony.gutierrez@amd.com           senderState(NULL)
62211308Santhony.gutierrez@amd.com    {
62311308Santhony.gutierrez@amd.com        if (req->hasPaddr()) {
62411308Santhony.gutierrez@amd.com            addr = req->getPaddr() & ~(_blkSize - 1);
62511308Santhony.gutierrez@amd.com            flags.set(VALID_ADDR);
62611308Santhony.gutierrez@amd.com        }
62711308Santhony.gutierrez@amd.com        size = _blkSize;
62811308Santhony.gutierrez@amd.com        flags.set(VALID_SIZE);
62911308Santhony.gutierrez@amd.com    }
63011308Santhony.gutierrez@amd.com
63111308Santhony.gutierrez@amd.com    /**
63211308Santhony.gutierrez@amd.com     * Alternate constructor for copying a packet.  Copy all fields
63311308Santhony.gutierrez@amd.com     * *except* if the original packet's data was dynamic, don't copy
63411308Santhony.gutierrez@amd.com     * that, as we can't guarantee that the new packet's lifetime is
63511308Santhony.gutierrez@amd.com     * less than that of the original packet.  In this case the new
63611639Salexandru.dutu@amd.com     * packet should allocate its own data.
63711308Santhony.gutierrez@amd.com     */
63811308Santhony.gutierrez@amd.com    Packet(Packet *pkt, bool clearFlags = false)
63911308Santhony.gutierrez@amd.com        :  cmd(pkt->cmd), req(pkt->req),
64011308Santhony.gutierrez@amd.com           data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL),
64111639Salexandru.dutu@amd.com           addr(pkt->addr), size(pkt->size), src(pkt->src), dest(pkt->dest),
64211308Santhony.gutierrez@amd.com           bytesValidStart(pkt->bytesValidStart),
64311308Santhony.gutierrez@amd.com           bytesValidEnd(pkt->bytesValidEnd),
64411308Santhony.gutierrez@amd.com           busFirstWordDelay(pkt->busFirstWordDelay),
64511308Santhony.gutierrez@amd.com           busLastWordDelay(pkt->busLastWordDelay),
64611639Salexandru.dutu@amd.com           senderState(pkt->senderState)
64711308Santhony.gutierrez@amd.com    {
64811308Santhony.gutierrez@amd.com        if (!clearFlags)
64911692Santhony.gutierrez@amd.com            flags.set(pkt->flags & COPY_FLAGS);
65011308Santhony.gutierrez@amd.com
65111308Santhony.gutierrez@amd.com        flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE));
65211308Santhony.gutierrez@amd.com        flags.set(pkt->flags & STATIC_DATA);
65311308Santhony.gutierrez@amd.com
65411308Santhony.gutierrez@amd.com    }
65511308Santhony.gutierrez@amd.com
65611308Santhony.gutierrez@amd.com    /**
65711308Santhony.gutierrez@amd.com     * clean up packet variables
65811308Santhony.gutierrez@amd.com     */
65911308Santhony.gutierrez@amd.com    ~Packet()
66011692Santhony.gutierrez@amd.com    {
66111308Santhony.gutierrez@amd.com        // If this is a request packet for which there's no response,
66211308Santhony.gutierrez@amd.com        // delete the request object here, since the requester will
66311308Santhony.gutierrez@amd.com        // never get the chance.
66411308Santhony.gutierrez@amd.com        if (req && isRequest() && !needsResponse())
66511308Santhony.gutierrez@amd.com            delete req;
66611308Santhony.gutierrez@amd.com        deleteData();
66711308Santhony.gutierrez@amd.com    }
66811308Santhony.gutierrez@amd.com
66911308Santhony.gutierrez@amd.com    /**
67011308Santhony.gutierrez@amd.com     * Reinitialize packet address and size from the associated
67111308Santhony.gutierrez@amd.com     * Request object, and reset other fields that may have been
67211308Santhony.gutierrez@amd.com     * modified by a previous transaction.  Typically called when a
67311308Santhony.gutierrez@amd.com     * statically allocated Request/Packet pair is reused for multiple
67411308Santhony.gutierrez@amd.com     * transactions.
67511308Santhony.gutierrez@amd.com     */
67611308Santhony.gutierrez@amd.com    void
67711308Santhony.gutierrez@amd.com    reinitFromRequest()
67811308Santhony.gutierrez@amd.com    {
67911308Santhony.gutierrez@amd.com        assert(req->hasPaddr());
68011308Santhony.gutierrez@amd.com        flags = 0;
68111308Santhony.gutierrez@amd.com        addr = req->getPaddr();
68211308Santhony.gutierrez@amd.com        size = req->getSize();
68311308Santhony.gutierrez@amd.com
68411308Santhony.gutierrez@amd.com        src = InvalidPortID;
68511308Santhony.gutierrez@amd.com        dest = InvalidPortID;
68611308Santhony.gutierrez@amd.com        bytesValidStart = 0;
68711308Santhony.gutierrez@amd.com        bytesValidEnd = 0;
68811308Santhony.gutierrez@amd.com        busFirstWordDelay = 0;
68911308Santhony.gutierrez@amd.com        busLastWordDelay = 0;
69011308Santhony.gutierrez@amd.com
69111308Santhony.gutierrez@amd.com        flags.set(VALID_ADDR|VALID_SIZE);
69211308Santhony.gutierrez@amd.com        deleteData();
69311308Santhony.gutierrez@amd.com    }
69411308Santhony.gutierrez@amd.com
69511308Santhony.gutierrez@amd.com    /**
69611308Santhony.gutierrez@amd.com     * Take a request packet and modify it in place to be suitable for
69711308Santhony.gutierrez@amd.com     * returning as a response to that request. The source field is
69811308Santhony.gutierrez@amd.com     * turned into the destination, and subsequently cleared. Note
69911308Santhony.gutierrez@amd.com     * that the latter is not necessary for atomic requests, but
70011308Santhony.gutierrez@amd.com     * causes no harm as neither field is valid.
70111308Santhony.gutierrez@amd.com     */
70211308Santhony.gutierrez@amd.com    void
70311308Santhony.gutierrez@amd.com    makeResponse()
70411308Santhony.gutierrez@amd.com    {
70511308Santhony.gutierrez@amd.com        assert(needsResponse());
70611308Santhony.gutierrez@amd.com        assert(isRequest());
70711308Santhony.gutierrez@amd.com        origCmd = cmd;
70811308Santhony.gutierrez@amd.com        cmd = cmd.responseCommand();
70911308Santhony.gutierrez@amd.com
71011308Santhony.gutierrez@amd.com        // responses are never express, even if the snoop that
71111308Santhony.gutierrez@amd.com        // triggered them was
71211308Santhony.gutierrez@amd.com        flags.clear(EXPRESS_SNOOP);
71311308Santhony.gutierrez@amd.com
71411308Santhony.gutierrez@amd.com        dest = src;
71511308Santhony.gutierrez@amd.com        clearSrc();
71611308Santhony.gutierrez@amd.com    }
71711308Santhony.gutierrez@amd.com
71811308Santhony.gutierrez@amd.com    void
71911308Santhony.gutierrez@amd.com    makeAtomicResponse()
72011308Santhony.gutierrez@amd.com    {
72111308Santhony.gutierrez@amd.com        makeResponse();
72211308Santhony.gutierrez@amd.com    }
72311308Santhony.gutierrez@amd.com
72411308Santhony.gutierrez@amd.com    void
72511308Santhony.gutierrez@amd.com    makeTimingResponse()
72611308Santhony.gutierrez@amd.com    {
72711308Santhony.gutierrez@amd.com        makeResponse();
72811308Santhony.gutierrez@amd.com    }
72911308Santhony.gutierrez@amd.com
73011308Santhony.gutierrez@amd.com    void
73111308Santhony.gutierrez@amd.com    setFunctionalResponseStatus(bool success)
73211308Santhony.gutierrez@amd.com    {
73311308Santhony.gutierrez@amd.com        if (!success) {
73411308Santhony.gutierrez@amd.com            if (isWrite()) {
73511308Santhony.gutierrez@amd.com                cmd = MemCmd::FunctionalWriteError;
73611308Santhony.gutierrez@amd.com            } else {
73711308Santhony.gutierrez@amd.com                cmd = MemCmd::FunctionalReadError;
73811308Santhony.gutierrez@amd.com            }
73911308Santhony.gutierrez@amd.com        }
74011308Santhony.gutierrez@amd.com    }
74111308Santhony.gutierrez@amd.com
74211308Santhony.gutierrez@amd.com    void
74311308Santhony.gutierrez@amd.com    setSize(unsigned size)
74411308Santhony.gutierrez@amd.com    {
74511308Santhony.gutierrez@amd.com        assert(!flags.isSet(VALID_SIZE));
74611308Santhony.gutierrez@amd.com
74711308Santhony.gutierrez@amd.com        this->size = size;
74811308Santhony.gutierrez@amd.com        flags.set(VALID_SIZE);
74911308Santhony.gutierrez@amd.com    }
75011308Santhony.gutierrez@amd.com
75111308Santhony.gutierrez@amd.com
75211308Santhony.gutierrez@amd.com    /**
75311308Santhony.gutierrez@amd.com     * Set the data pointer to the following value that should not be
75411308Santhony.gutierrez@amd.com     * freed.
75511308Santhony.gutierrez@amd.com     */
75611308Santhony.gutierrez@amd.com    template <typename T>
75711308Santhony.gutierrez@amd.com    void
75811308Santhony.gutierrez@amd.com    dataStatic(T *p)
75911308Santhony.gutierrez@amd.com    {
76011308Santhony.gutierrez@amd.com        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
76111308Santhony.gutierrez@amd.com        data = (PacketDataPtr)p;
76211308Santhony.gutierrez@amd.com        flags.set(STATIC_DATA);
76311308Santhony.gutierrez@amd.com    }
76411308Santhony.gutierrez@amd.com
76511308Santhony.gutierrez@amd.com    /**
76611308Santhony.gutierrez@amd.com     * Set the data pointer to a value that should have delete []
76711308Santhony.gutierrez@amd.com     * called on it.
76811308Santhony.gutierrez@amd.com     */
76911308Santhony.gutierrez@amd.com    template <typename T>
77011308Santhony.gutierrez@amd.com    void
77111308Santhony.gutierrez@amd.com    dataDynamicArray(T *p)
77211308Santhony.gutierrez@amd.com    {
77311308Santhony.gutierrez@amd.com        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
77411308Santhony.gutierrez@amd.com        data = (PacketDataPtr)p;
77511308Santhony.gutierrez@amd.com        flags.set(DYNAMIC_DATA|ARRAY_DATA);
77611308Santhony.gutierrez@amd.com    }
77711308Santhony.gutierrez@amd.com
77811308Santhony.gutierrez@amd.com    /**
77911308Santhony.gutierrez@amd.com     * set the data pointer to a value that should have delete called
78011308Santhony.gutierrez@amd.com     * on it.
78111308Santhony.gutierrez@amd.com     */
78211308Santhony.gutierrez@amd.com    template <typename T>
78311308Santhony.gutierrez@amd.com    void
78411308Santhony.gutierrez@amd.com    dataDynamic(T *p)
78511308Santhony.gutierrez@amd.com    {
78611308Santhony.gutierrez@amd.com        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA));
78711308Santhony.gutierrez@amd.com        data = (PacketDataPtr)p;
78811308Santhony.gutierrez@amd.com        flags.set(DYNAMIC_DATA);
78911308Santhony.gutierrez@amd.com    }
79011308Santhony.gutierrez@amd.com
79111308Santhony.gutierrez@amd.com    /**
79211308Santhony.gutierrez@amd.com     * get a pointer to the data ptr.
79311308Santhony.gutierrez@amd.com     */
79411308Santhony.gutierrez@amd.com    template <typename T>
79511308Santhony.gutierrez@amd.com    T*
79611308Santhony.gutierrez@amd.com    getPtr(bool null_ok = false)
79711308Santhony.gutierrez@amd.com    {
79811308Santhony.gutierrez@amd.com        assert(null_ok || flags.isSet(STATIC_DATA|DYNAMIC_DATA));
79911308Santhony.gutierrez@amd.com        return (T*)data;
80011308Santhony.gutierrez@amd.com    }
80111308Santhony.gutierrez@amd.com
80211308Santhony.gutierrez@amd.com    /**
80311308Santhony.gutierrez@amd.com     * return the value of what is pointed to in the packet.
80411308Santhony.gutierrez@amd.com     */
80511308Santhony.gutierrez@amd.com    template <typename T>
80611308Santhony.gutierrez@amd.com    T get();
80711308Santhony.gutierrez@amd.com
80811308Santhony.gutierrez@amd.com    /**
80911308Santhony.gutierrez@amd.com     * set the value in the data pointer to v.
81011308Santhony.gutierrez@amd.com     */
81111308Santhony.gutierrez@amd.com    template <typename T>
81211308Santhony.gutierrez@amd.com    void set(T v);
81311308Santhony.gutierrez@amd.com
81411308Santhony.gutierrez@amd.com    /**
81511308Santhony.gutierrez@amd.com     * Copy data into the packet from the provided pointer.
81611308Santhony.gutierrez@amd.com     */
81711308Santhony.gutierrez@amd.com    void
81811308Santhony.gutierrez@amd.com    setData(uint8_t *p)
81911308Santhony.gutierrez@amd.com    {
82011308Santhony.gutierrez@amd.com        if (p != getPtr<uint8_t>())
82111308Santhony.gutierrez@amd.com            std::memcpy(getPtr<uint8_t>(), p, getSize());
82211308Santhony.gutierrez@amd.com    }
82311308Santhony.gutierrez@amd.com
82411308Santhony.gutierrez@amd.com    /**
82511308Santhony.gutierrez@amd.com     * Copy data into the packet from the provided block pointer,
82611308Santhony.gutierrez@amd.com     * which is aligned to the given block size.
82711308Santhony.gutierrez@amd.com     */
82811308Santhony.gutierrez@amd.com    void
82911308Santhony.gutierrez@amd.com    setDataFromBlock(uint8_t *blk_data, int blkSize)
83011308Santhony.gutierrez@amd.com    {
83111308Santhony.gutierrez@amd.com        setData(blk_data + getOffset(blkSize));
83211308Santhony.gutierrez@amd.com    }
83311308Santhony.gutierrez@amd.com
83411308Santhony.gutierrez@amd.com    /**
83511308Santhony.gutierrez@amd.com     * Copy data from the packet to the provided block pointer, which
83611308Santhony.gutierrez@amd.com     * is aligned to the given block size.
83711308Santhony.gutierrez@amd.com     */
83811308Santhony.gutierrez@amd.com    void
83911308Santhony.gutierrez@amd.com    writeData(uint8_t *p)
84011308Santhony.gutierrez@amd.com    {
84111308Santhony.gutierrez@amd.com        std::memcpy(p, getPtr<uint8_t>(), getSize());
84211308Santhony.gutierrez@amd.com    }
84311308Santhony.gutierrez@amd.com
84411308Santhony.gutierrez@amd.com    /**
84511308Santhony.gutierrez@amd.com     * Copy data from the packet to the memory at the provided pointer.
84611308Santhony.gutierrez@amd.com     */
84711308Santhony.gutierrez@amd.com    void
84811308Santhony.gutierrez@amd.com    writeDataToBlock(uint8_t *blk_data, int blkSize)
84911308Santhony.gutierrez@amd.com    {
85011308Santhony.gutierrez@amd.com        writeData(blk_data + getOffset(blkSize));
85111308Santhony.gutierrez@amd.com    }
85211308Santhony.gutierrez@amd.com
85311308Santhony.gutierrez@amd.com    /**
85411308Santhony.gutierrez@amd.com     * delete the data pointed to in the data pointer. Ok to call to
85511308Santhony.gutierrez@amd.com     * matter how data was allocted.
85611308Santhony.gutierrez@amd.com     */
85711308Santhony.gutierrez@amd.com    void
85811308Santhony.gutierrez@amd.com    deleteData()
85911308Santhony.gutierrez@amd.com    {
86011308Santhony.gutierrez@amd.com        if (flags.isSet(ARRAY_DATA))
86111308Santhony.gutierrez@amd.com            delete [] data;
86211308Santhony.gutierrez@amd.com        else if (flags.isSet(DYNAMIC_DATA))
86311308Santhony.gutierrez@amd.com            delete data;
86411308Santhony.gutierrez@amd.com
86511308Santhony.gutierrez@amd.com        flags.clear(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA);
86611308Santhony.gutierrez@amd.com        data = NULL;
86711308Santhony.gutierrez@amd.com    }
86811308Santhony.gutierrez@amd.com
86911308Santhony.gutierrez@amd.com    /** If there isn't data in the packet, allocate some. */
87011308Santhony.gutierrez@amd.com    void
87111308Santhony.gutierrez@amd.com    allocate()
87211308Santhony.gutierrez@amd.com    {
87311308Santhony.gutierrez@amd.com        if (data) {
87411308Santhony.gutierrez@amd.com            assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA));
87511308Santhony.gutierrez@amd.com            return;
87611308Santhony.gutierrez@amd.com        }
87711308Santhony.gutierrez@amd.com
87811308Santhony.gutierrez@amd.com        assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA));
87911308Santhony.gutierrez@amd.com        flags.set(DYNAMIC_DATA|ARRAY_DATA);
88011308Santhony.gutierrez@amd.com        data = new uint8_t[getSize()];
88111308Santhony.gutierrez@amd.com    }
88211308Santhony.gutierrez@amd.com
88311308Santhony.gutierrez@amd.com    /**
88411308Santhony.gutierrez@amd.com     * Check a functional request against a memory value represented
88511308Santhony.gutierrez@amd.com     * by a base/size pair and an associated data array.  If the
88611308Santhony.gutierrez@amd.com     * functional request is a read, it may be satisfied by the memory
88711308Santhony.gutierrez@amd.com     * value.  If the functional request is a write, it may update the
88811308Santhony.gutierrez@amd.com     * memory value.
88911308Santhony.gutierrez@amd.com     */
89011308Santhony.gutierrez@amd.com    bool checkFunctional(Printable *obj, Addr base, int size, uint8_t *data);
89111308Santhony.gutierrez@amd.com
89211308Santhony.gutierrez@amd.com    /**
89311308Santhony.gutierrez@amd.com     * Check a functional request against a memory value stored in
89411308Santhony.gutierrez@amd.com     * another packet (i.e. an in-transit request or response).
89511308Santhony.gutierrez@amd.com     */
89611308Santhony.gutierrez@amd.com    bool
89711308Santhony.gutierrez@amd.com    checkFunctional(PacketPtr other)
89811308Santhony.gutierrez@amd.com    {
89911308Santhony.gutierrez@amd.com        uint8_t *data = other->hasData() ? other->getPtr<uint8_t>() : NULL;
90011308Santhony.gutierrez@amd.com        return checkFunctional(other, other->getAddr(), other->getSize(),
90111308Santhony.gutierrez@amd.com                               data);
90211308Santhony.gutierrez@amd.com    }
90311308Santhony.gutierrez@amd.com
90411308Santhony.gutierrez@amd.com    /**
90511308Santhony.gutierrez@amd.com     * Push label for PrintReq (safe to call unconditionally).
90611308Santhony.gutierrez@amd.com     */
90711308Santhony.gutierrez@amd.com    void
90811308Santhony.gutierrez@amd.com    pushLabel(const std::string &lbl)
90911308Santhony.gutierrez@amd.com    {
91011308Santhony.gutierrez@amd.com        if (isPrint())
91111308Santhony.gutierrez@amd.com            safe_cast<PrintReqState*>(senderState)->pushLabel(lbl);
91211308Santhony.gutierrez@amd.com    }
91311308Santhony.gutierrez@amd.com
91411308Santhony.gutierrez@amd.com    /**
91511308Santhony.gutierrez@amd.com     * Pop label for PrintReq (safe to call unconditionally).
91611308Santhony.gutierrez@amd.com     */
91711308Santhony.gutierrez@amd.com    void
91811308Santhony.gutierrez@amd.com    popLabel()
91911308Santhony.gutierrez@amd.com    {
92011308Santhony.gutierrez@amd.com        if (isPrint())
92111308Santhony.gutierrez@amd.com            safe_cast<PrintReqState*>(senderState)->popLabel();
92211308Santhony.gutierrez@amd.com    }
92311308Santhony.gutierrez@amd.com
92411308Santhony.gutierrez@amd.com    void print(std::ostream &o, int verbosity = 0,
92511308Santhony.gutierrez@amd.com               const std::string &prefix = "") const;
92611308Santhony.gutierrez@amd.com
92711308Santhony.gutierrez@amd.com    /**
92811308Santhony.gutierrez@amd.com     * A no-args wrapper of print(std::ostream...)
92911308Santhony.gutierrez@amd.com     * meant to be invoked from DPRINTFs
93011308Santhony.gutierrez@amd.com     * avoiding string overheads in fast mode
93111308Santhony.gutierrez@amd.com     * @return string with the request's type and start<->end addresses
93211308Santhony.gutierrez@amd.com     */
93311308Santhony.gutierrez@amd.com    std::string print() const;
93411308Santhony.gutierrez@amd.com};
93511308Santhony.gutierrez@amd.com
93611308Santhony.gutierrez@amd.com#endif //__MEM_PACKET_HH
93711308Santhony.gutierrez@amd.com