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