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