packet.hh revision 12349
17139Sgblack@eecs.umich.edu/* 27139Sgblack@eecs.umich.edu * Copyright (c) 2012-2017 ARM Limited 37139Sgblack@eecs.umich.edu * All rights reserved 47139Sgblack@eecs.umich.edu * 57139Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall 67139Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual 77139Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating 87139Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software 97139Sgblack@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 107139Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 117139Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 127139Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form. 137139Sgblack@eecs.umich.edu * 147139Sgblack@eecs.umich.edu * Copyright (c) 2006 The Regents of The University of Michigan 157139Sgblack@eecs.umich.edu * Copyright (c) 2010,2015 Advanced Micro Devices, Inc. 167139Sgblack@eecs.umich.edu * All rights reserved. 177139Sgblack@eecs.umich.edu * 187139Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 197139Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 207139Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 217139Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 227139Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 237139Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 247139Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 257139Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 267139Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 277139Sgblack@eecs.umich.edu * this software without specific prior written permission. 287139Sgblack@eecs.umich.edu * 297139Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 307139Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 317139Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 327139Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 337139Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 347139Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 357139Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 367139Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 377139Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 387255Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 397243Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 407243Sgblack@eecs.umich.edu * 417255Sgblack@eecs.umich.edu * Authors: Ron Dreslinski 427255Sgblack@eecs.umich.edu * Steve Reinhardt 437243Sgblack@eecs.umich.edu * Ali Saidi 447243Sgblack@eecs.umich.edu * Andreas Hansson 457255Sgblack@eecs.umich.edu * Nikos Nikoleris 467255Sgblack@eecs.umich.edu */ 477255Sgblack@eecs.umich.edu 487255Sgblack@eecs.umich.edu/** 497255Sgblack@eecs.umich.edu * @file 507255Sgblack@eecs.umich.edu * Declaration of the Packet class. 517255Sgblack@eecs.umich.edu */ 527255Sgblack@eecs.umich.edu 537255Sgblack@eecs.umich.edu#ifndef __MEM_PACKET_HH__ 547255Sgblack@eecs.umich.edu#define __MEM_PACKET_HH__ 557255Sgblack@eecs.umich.edu 567256Sgblack@eecs.umich.edu#include <bitset> 577256Sgblack@eecs.umich.edu#include <cassert> 587255Sgblack@eecs.umich.edu#include <list> 597256Sgblack@eecs.umich.edu 607255Sgblack@eecs.umich.edu#include "base/cast.hh" 617256Sgblack@eecs.umich.edu#include "base/compiler.hh" 627255Sgblack@eecs.umich.edu#include "base/flags.hh" 637255Sgblack@eecs.umich.edu#include "base/logging.hh" 647258Sgblack@eecs.umich.edu#include "base/printable.hh" 657258Sgblack@eecs.umich.edu#include "base/types.hh" 667255Sgblack@eecs.umich.edu#include "mem/request.hh" 677258Sgblack@eecs.umich.edu#include "sim/core.hh" 687255Sgblack@eecs.umich.edu 697258Sgblack@eecs.umich.educlass Packet; 707255Sgblack@eecs.umich.edutypedef Packet *PacketPtr; 717243Sgblack@eecs.umich.edutypedef uint8_t* PacketDataPtr; 727255Sgblack@eecs.umich.edutypedef std::list<PacketPtr> PacketList; 737243Sgblack@eecs.umich.edu 747243Sgblack@eecs.umich.educlass MemCmd 757243Sgblack@eecs.umich.edu{ 767243Sgblack@eecs.umich.edu friend class Packet; 777139Sgblack@eecs.umich.edu 787188Sgblack@eecs.umich.edu public: 797188Sgblack@eecs.umich.edu /** 807188Sgblack@eecs.umich.edu * List of all commands associated with a packet. 817188Sgblack@eecs.umich.edu */ 827188Sgblack@eecs.umich.edu enum Command 837139Sgblack@eecs.umich.edu { 847139Sgblack@eecs.umich.edu InvalidCmd, 857139Sgblack@eecs.umich.edu ReadReq, 867139Sgblack@eecs.umich.edu ReadResp, 877188Sgblack@eecs.umich.edu ReadRespWithInvalidate, 887188Sgblack@eecs.umich.edu WriteReq, 897188Sgblack@eecs.umich.edu WriteResp, 907188Sgblack@eecs.umich.edu WritebackDirty, 917188Sgblack@eecs.umich.edu WritebackClean, 927188Sgblack@eecs.umich.edu WriteClean, // writes dirty data below without evicting 937139Sgblack@eecs.umich.edu CleanEvict, 947146Sgblack@eecs.umich.edu SoftPFReq, 957141Sgblack@eecs.umich.edu HardPFReq, 967139Sgblack@eecs.umich.edu SoftPFResp, 977139Sgblack@eecs.umich.edu HardPFResp, 987139Sgblack@eecs.umich.edu WriteLineReq, 997146Sgblack@eecs.umich.edu UpgradeReq, 1007141Sgblack@eecs.umich.edu SCUpgradeReq, // Special "weak" upgrade for StoreCond 1017139Sgblack@eecs.umich.edu UpgradeResp, 1027146Sgblack@eecs.umich.edu SCUpgradeFailReq, // Failed SCUpgradeReq in MSHR (never sent) 1037141Sgblack@eecs.umich.edu UpgradeFailResp, // Valid for SCUpgradeReq only 1047139Sgblack@eecs.umich.edu ReadExReq, 1057139Sgblack@eecs.umich.edu ReadExResp, 1067139Sgblack@eecs.umich.edu ReadCleanReq, 1077139Sgblack@eecs.umich.edu ReadSharedReq, 1087139Sgblack@eecs.umich.edu LoadLockedReq, 1097188Sgblack@eecs.umich.edu StoreCondReq, 1107188Sgblack@eecs.umich.edu StoreCondFailReq, // Failed StoreCondReq in MSHR (never sent) 1117188Sgblack@eecs.umich.edu StoreCondResp, 1127188Sgblack@eecs.umich.edu SwapReq, 1137188Sgblack@eecs.umich.edu SwapResp, 1147188Sgblack@eecs.umich.edu MessageReq, 1157188Sgblack@eecs.umich.edu MessageResp, 1167188Sgblack@eecs.umich.edu MemFenceReq, 1177188Sgblack@eecs.umich.edu MemFenceResp, 1187188Sgblack@eecs.umich.edu CleanSharedReq, 1197188Sgblack@eecs.umich.edu CleanSharedResp, 1207188Sgblack@eecs.umich.edu CleanInvalidReq, 1217188Sgblack@eecs.umich.edu CleanInvalidResp, 1227188Sgblack@eecs.umich.edu // Error responses 1237188Sgblack@eecs.umich.edu // @TODO these should be classified as responses rather than 1247188Sgblack@eecs.umich.edu // requests; coding them as requests initially for backwards 1257188Sgblack@eecs.umich.edu // compatibility 1267188Sgblack@eecs.umich.edu InvalidDestError, // packet dest field invalid 1277188Sgblack@eecs.umich.edu BadAddressError, // memory address invalid 1287188Sgblack@eecs.umich.edu FunctionalReadError, // unable to fulfill functional read 1297139Sgblack@eecs.umich.edu FunctionalWriteError, // unable to fulfill functional write 1307139Sgblack@eecs.umich.edu // Fake simulator-only commands 1317139Sgblack@eecs.umich.edu PrintReq, // Print state matching address 1327139Sgblack@eecs.umich.edu FlushReq, //request for a cache flush 1337139Sgblack@eecs.umich.edu InvalidateReq, // request for address to be invalidated 1347139Sgblack@eecs.umich.edu InvalidateResp, 1357139Sgblack@eecs.umich.edu NUM_MEM_CMDS 1367139Sgblack@eecs.umich.edu }; 1377139Sgblack@eecs.umich.edu 1387139Sgblack@eecs.umich.edu private: 1397139Sgblack@eecs.umich.edu /** 1407139Sgblack@eecs.umich.edu * List of command attributes. 1417139Sgblack@eecs.umich.edu */ 1427139Sgblack@eecs.umich.edu enum Attribute 1437139Sgblack@eecs.umich.edu { 1447139Sgblack@eecs.umich.edu IsRead, //!< Data flows from responder to requester 1457139Sgblack@eecs.umich.edu IsWrite, //!< Data flows from requester to responder 1467139Sgblack@eecs.umich.edu IsUpgrade, 1477139Sgblack@eecs.umich.edu IsInvalidate, 1487139Sgblack@eecs.umich.edu IsClean, //!< Cleans any existing dirty blocks 1497139Sgblack@eecs.umich.edu NeedsWritable, //!< Requires writable copy to complete in-cache 1507188Sgblack@eecs.umich.edu IsRequest, //!< Issued by requester 1517188Sgblack@eecs.umich.edu IsResponse, //!< Issue by responder 1527188Sgblack@eecs.umich.edu NeedsResponse, //!< Requester needs response from target 1537188Sgblack@eecs.umich.edu IsEviction, 1547139Sgblack@eecs.umich.edu IsSWPrefetch, 1557188Sgblack@eecs.umich.edu IsHWPrefetch, 1567139Sgblack@eecs.umich.edu IsLlsc, //!< Alpha/MIPS LL or SC access 1577188Sgblack@eecs.umich.edu HasData, //!< There is an associated payload 1587139Sgblack@eecs.umich.edu IsError, //!< Error response 1597139Sgblack@eecs.umich.edu IsPrint, //!< Print state matching address (for debugging) 1607139Sgblack@eecs.umich.edu IsFlush, //!< Flush the address from caches 1617139Sgblack@eecs.umich.edu FromCache, //!< Request originated from a caching agent 1627139Sgblack@eecs.umich.edu NUM_COMMAND_ATTRIBUTES 1637139Sgblack@eecs.umich.edu }; 1647139Sgblack@eecs.umich.edu 1657139Sgblack@eecs.umich.edu /** 1667210Sgblack@eecs.umich.edu * Structure that defines attributes and other data associated 1677210Sgblack@eecs.umich.edu * with a Command. 1687210Sgblack@eecs.umich.edu */ 1697210Sgblack@eecs.umich.edu struct CommandInfo 1707210Sgblack@eecs.umich.edu { 1717210Sgblack@eecs.umich.edu /// Set of attribute flags. 1727210Sgblack@eecs.umich.edu const std::bitset<NUM_COMMAND_ATTRIBUTES> attributes; 1737227Sgblack@eecs.umich.edu /// Corresponding response for requests; InvalidCmd if no 1747227Sgblack@eecs.umich.edu /// response is applicable. 1757227Sgblack@eecs.umich.edu const Command response; 1767227Sgblack@eecs.umich.edu /// String representation (for printing) 1777227Sgblack@eecs.umich.edu const std::string str; 1787227Sgblack@eecs.umich.edu }; 1797227Sgblack@eecs.umich.edu 1807227Sgblack@eecs.umich.edu /// Array to map Command enum to associated info. 1817210Sgblack@eecs.umich.edu static const CommandInfo commandInfo[]; 1827237Sgblack@eecs.umich.edu 1837237Sgblack@eecs.umich.edu private: 1847237Sgblack@eecs.umich.edu 1857237Sgblack@eecs.umich.edu Command cmd; 1867237Sgblack@eecs.umich.edu 1877237Sgblack@eecs.umich.edu bool 1887237Sgblack@eecs.umich.edu testCmdAttrib(MemCmd::Attribute attrib) const 1897210Sgblack@eecs.umich.edu { 1907227Sgblack@eecs.umich.edu return commandInfo[cmd].attributes[attrib] != 0; 1917210Sgblack@eecs.umich.edu } 1927227Sgblack@eecs.umich.edu 1937210Sgblack@eecs.umich.edu public: 1947210Sgblack@eecs.umich.edu 1957210Sgblack@eecs.umich.edu bool isRead() const { return testCmdAttrib(IsRead); } 1967210Sgblack@eecs.umich.edu bool isWrite() const { return testCmdAttrib(IsWrite); } 1977210Sgblack@eecs.umich.edu bool isUpgrade() const { return testCmdAttrib(IsUpgrade); } 1987240Sgblack@eecs.umich.edu bool isRequest() const { return testCmdAttrib(IsRequest); } 1997235Sgblack@eecs.umich.edu bool isResponse() const { return testCmdAttrib(IsResponse); } 2007235Sgblack@eecs.umich.edu bool needsWritable() const { return testCmdAttrib(NeedsWritable); } 2017235Sgblack@eecs.umich.edu bool needsResponse() const { return testCmdAttrib(NeedsResponse); } 2027235Sgblack@eecs.umich.edu bool isInvalidate() const { return testCmdAttrib(IsInvalidate); } 2037235Sgblack@eecs.umich.edu bool isEviction() const { return testCmdAttrib(IsEviction); } 2047235Sgblack@eecs.umich.edu bool isClean() const { return testCmdAttrib(IsClean); } 2057240Sgblack@eecs.umich.edu bool fromCache() const { return testCmdAttrib(FromCache); } 2067240Sgblack@eecs.umich.edu 2077240Sgblack@eecs.umich.edu /** 2087240Sgblack@eecs.umich.edu * A writeback is an eviction that carries data. 2097240Sgblack@eecs.umich.edu */ 2107240Sgblack@eecs.umich.edu bool isWriteback() const { return testCmdAttrib(IsEviction) && 2117240Sgblack@eecs.umich.edu testCmdAttrib(HasData); } 2127240Sgblack@eecs.umich.edu 2137240Sgblack@eecs.umich.edu /** 2147240Sgblack@eecs.umich.edu * Check if this particular packet type carries payload data. Note 2157210Sgblack@eecs.umich.edu * that this does not reflect if the data pointer of the packet is 2167210Sgblack@eecs.umich.edu * valid or not. 2177210Sgblack@eecs.umich.edu */ 2187210Sgblack@eecs.umich.edu bool hasData() const { return testCmdAttrib(HasData); } 2197210Sgblack@eecs.umich.edu bool isLLSC() const { return testCmdAttrib(IsLlsc); } 2207227Sgblack@eecs.umich.edu bool isSWPrefetch() const { return testCmdAttrib(IsSWPrefetch); } 2217227Sgblack@eecs.umich.edu bool isHWPrefetch() const { return testCmdAttrib(IsHWPrefetch); } 2227227Sgblack@eecs.umich.edu bool isPrefetch() const { return testCmdAttrib(IsSWPrefetch) || 2237227Sgblack@eecs.umich.edu testCmdAttrib(IsHWPrefetch); } 2247227Sgblack@eecs.umich.edu bool isError() const { return testCmdAttrib(IsError); } 2257227Sgblack@eecs.umich.edu bool isPrint() const { return testCmdAttrib(IsPrint); } 2267210Sgblack@eecs.umich.edu bool isFlush() const { return testCmdAttrib(IsFlush); } 2277235Sgblack@eecs.umich.edu 2287235Sgblack@eecs.umich.edu Command 2297235Sgblack@eecs.umich.edu responseCommand() const 2307235Sgblack@eecs.umich.edu { 2317235Sgblack@eecs.umich.edu return commandInfo[cmd].response; 2327235Sgblack@eecs.umich.edu } 2337235Sgblack@eecs.umich.edu 2347235Sgblack@eecs.umich.edu /// Return the string to a cmd given by idx. 2357210Sgblack@eecs.umich.edu const std::string &toString() const { return commandInfo[cmd].str; } 2367235Sgblack@eecs.umich.edu int toInt() const { return (int)cmd; } 2377210Sgblack@eecs.umich.edu 2387235Sgblack@eecs.umich.edu MemCmd(Command _cmd) : cmd(_cmd) { } 2397210Sgblack@eecs.umich.edu MemCmd(int _cmd) : cmd((Command)_cmd) { } 2407210Sgblack@eecs.umich.edu MemCmd() : cmd(InvalidCmd) { } 2417210Sgblack@eecs.umich.edu 2427210Sgblack@eecs.umich.edu bool operator==(MemCmd c2) const { return (cmd == c2.cmd); } 2437210Sgblack@eecs.umich.edu bool operator!=(MemCmd c2) const { return (cmd != c2.cmd); } 2447211Sgblack@eecs.umich.edu}; 2457211Sgblack@eecs.umich.edu 2467211Sgblack@eecs.umich.edu/** 2477210Sgblack@eecs.umich.edu * A Packet is used to encapsulate a transfer between two objects in 2487235Sgblack@eecs.umich.edu * the memory system (e.g., the L1 and L2 cache). (In contrast, a 2497235Sgblack@eecs.umich.edu * single Request travels all the way from the requester to the 2507235Sgblack@eecs.umich.edu * ultimate destination and back, possibly being conveyed by several 2517235Sgblack@eecs.umich.edu * different Packets along the way.) 2527235Sgblack@eecs.umich.edu */ 2537235Sgblack@eecs.umich.educlass Packet : public Printable 2547235Sgblack@eecs.umich.edu{ 2557235Sgblack@eecs.umich.edu public: 2567210Sgblack@eecs.umich.edu typedef uint32_t FlagsType; 2577235Sgblack@eecs.umich.edu typedef ::Flags<FlagsType> Flags; 2587210Sgblack@eecs.umich.edu 2597235Sgblack@eecs.umich.edu private: 2607210Sgblack@eecs.umich.edu 2617210Sgblack@eecs.umich.edu enum : FlagsType { 2627211Sgblack@eecs.umich.edu // Flags to transfer across when copying a packet 2637211Sgblack@eecs.umich.edu COPY_FLAGS = 0x0000003F, 2647211Sgblack@eecs.umich.edu 2657210Sgblack@eecs.umich.edu // Does this packet have sharers (which means it should not be 2667210Sgblack@eecs.umich.edu // considered writable) or not. See setHasSharers below. 2677210Sgblack@eecs.umich.edu HAS_SHARERS = 0x00000001, 2687210Sgblack@eecs.umich.edu 2697235Sgblack@eecs.umich.edu // Special control flags 2707235Sgblack@eecs.umich.edu /// Special timing-mode atomic snoop for multi-level coherence. 2717235Sgblack@eecs.umich.edu EXPRESS_SNOOP = 0x00000002, 2727235Sgblack@eecs.umich.edu 2737235Sgblack@eecs.umich.edu /// Allow a responding cache to inform the cache hierarchy 2747235Sgblack@eecs.umich.edu /// that it had a writable copy before responding. See 2757235Sgblack@eecs.umich.edu /// setResponderHadWritable below. 2767235Sgblack@eecs.umich.edu RESPONDER_HAD_WRITABLE = 0x00000004, 2777210Sgblack@eecs.umich.edu 2787235Sgblack@eecs.umich.edu // Snoop co-ordination flag to indicate that a cache is 2797210Sgblack@eecs.umich.edu // responding to a snoop. See setCacheResponding below. 2807235Sgblack@eecs.umich.edu CACHE_RESPONDING = 0x00000008, 2817210Sgblack@eecs.umich.edu 2827210Sgblack@eecs.umich.edu // The writeback/writeclean should be propagated further 2837210Sgblack@eecs.umich.edu // downstream by the receiver 2847210Sgblack@eecs.umich.edu WRITE_THROUGH = 0x00000010, 2857210Sgblack@eecs.umich.edu 2867227Sgblack@eecs.umich.edu // Response co-ordination flag for cache maintenance 2877227Sgblack@eecs.umich.edu // operations 2887227Sgblack@eecs.umich.edu SATISFIED = 0x00000020, 2897227Sgblack@eecs.umich.edu 2907227Sgblack@eecs.umich.edu /// Are the 'addr' and 'size' fields valid? 2917227Sgblack@eecs.umich.edu VALID_ADDR = 0x00000100, 2927210Sgblack@eecs.umich.edu VALID_SIZE = 0x00000200, 2937235Sgblack@eecs.umich.edu 2947235Sgblack@eecs.umich.edu /// Is the data pointer set to a value that shouldn't be freed 2957235Sgblack@eecs.umich.edu /// when the packet is destroyed? 2967235Sgblack@eecs.umich.edu STATIC_DATA = 0x00001000, 2977235Sgblack@eecs.umich.edu /// The data pointer points to a value that should be freed when 2987235Sgblack@eecs.umich.edu /// the packet is destroyed. The pointer is assumed to be pointing 2997235Sgblack@eecs.umich.edu /// to an array, and delete [] is consequently called 3007235Sgblack@eecs.umich.edu DYNAMIC_DATA = 0x00002000, 3017210Sgblack@eecs.umich.edu 3027235Sgblack@eecs.umich.edu /// suppress the error if this packet encounters a functional 3037210Sgblack@eecs.umich.edu /// access failure. 3047235Sgblack@eecs.umich.edu SUPPRESS_FUNC_ERROR = 0x00008000, 3057210Sgblack@eecs.umich.edu 3067210Sgblack@eecs.umich.edu // Signal block present to squash prefetch and cache evict packets 3077210Sgblack@eecs.umich.edu // through express snoop flag 3087210Sgblack@eecs.umich.edu BLOCK_CACHED = 0x00010000 3097250Sgblack@eecs.umich.edu }; 3107235Sgblack@eecs.umich.edu 3117235Sgblack@eecs.umich.edu Flags flags; 3127235Sgblack@eecs.umich.edu 3137235Sgblack@eecs.umich.edu public: 3147235Sgblack@eecs.umich.edu typedef MemCmd::Command Command; 3157235Sgblack@eecs.umich.edu 3167250Sgblack@eecs.umich.edu /// The command field of the packet. 3177250Sgblack@eecs.umich.edu MemCmd cmd; 3187250Sgblack@eecs.umich.edu 3197250Sgblack@eecs.umich.edu /// A pointer to the original request. 3207250Sgblack@eecs.umich.edu const RequestPtr req; 3217250Sgblack@eecs.umich.edu 3227250Sgblack@eecs.umich.edu private: 3237250Sgblack@eecs.umich.edu /** 3247250Sgblack@eecs.umich.edu * A pointer to the data being transfered. It can be differnt 3257250Sgblack@eecs.umich.edu * sizes at each level of the heirarchy so it belongs in the 3267250Sgblack@eecs.umich.edu * packet, not request. This may or may not be populated when a 3277250Sgblack@eecs.umich.edu * responder recieves the packet. If not populated it memory should 3287210Sgblack@eecs.umich.edu * be allocated. 3297210Sgblack@eecs.umich.edu */ 3307210Sgblack@eecs.umich.edu PacketDataPtr data; 3317210Sgblack@eecs.umich.edu 3327210Sgblack@eecs.umich.edu /// The address of the request. This address could be virtual or 3337210Sgblack@eecs.umich.edu /// physical, depending on the system configuration. 3347210Sgblack@eecs.umich.edu Addr addr; 3357210Sgblack@eecs.umich.edu 3367210Sgblack@eecs.umich.edu /// True if the request targets the secure memory space. 3377194Sgblack@eecs.umich.edu bool _isSecure; 3387194Sgblack@eecs.umich.edu 3397194Sgblack@eecs.umich.edu /// The size of the request or transfer. 3407194Sgblack@eecs.umich.edu unsigned size; 3417194Sgblack@eecs.umich.edu 3427194Sgblack@eecs.umich.edu /** 3437194Sgblack@eecs.umich.edu * Track the bytes found that satisfy a functional read. 3447194Sgblack@eecs.umich.edu */ 3457194Sgblack@eecs.umich.edu std::vector<bool> bytesValid; 3467194Sgblack@eecs.umich.edu 3477194Sgblack@eecs.umich.edu public: 3487194Sgblack@eecs.umich.edu 3497194Sgblack@eecs.umich.edu /** 3507216Sgblack@eecs.umich.edu * The extra delay from seeing the packet until the header is 3517194Sgblack@eecs.umich.edu * transmitted. This delay is used to communicate the crossbar 3527224Sgblack@eecs.umich.edu * forwarding latency to the neighbouring object (e.g. a cache) 3537194Sgblack@eecs.umich.edu * that actually makes the packet wait. As the delay is relative, 3547224Sgblack@eecs.umich.edu * a 32-bit unsigned should be sufficient. 3557194Sgblack@eecs.umich.edu */ 3567218Sgblack@eecs.umich.edu uint32_t headerDelay; 3577194Sgblack@eecs.umich.edu 3587216Sgblack@eecs.umich.edu /** 3597194Sgblack@eecs.umich.edu * Keep track of the extra delay incurred by snooping upwards 3607218Sgblack@eecs.umich.edu * before sending a request down the memory system. This is used 3617194Sgblack@eecs.umich.edu * by the coherent crossbar to account for the additional request 3627194Sgblack@eecs.umich.edu * delay. 3637194Sgblack@eecs.umich.edu */ 3647194Sgblack@eecs.umich.edu uint32_t snoopDelay; 3657194Sgblack@eecs.umich.edu 3667194Sgblack@eecs.umich.edu /** 3677194Sgblack@eecs.umich.edu * The extra pipelining delay from seeing the packet until the end of 3687194Sgblack@eecs.umich.edu * payload is transmitted by the component that provided it (if 3697194Sgblack@eecs.umich.edu * any). This includes the header delay. Similar to the header 3707194Sgblack@eecs.umich.edu * delay, this is used to make up for the fact that the 3717194Sgblack@eecs.umich.edu * crossbar does not make the packet wait. As the delay is 3727194Sgblack@eecs.umich.edu * relative, a 32-bit unsigned should be sufficient. 3737194Sgblack@eecs.umich.edu */ 3747194Sgblack@eecs.umich.edu uint32_t payloadDelay; 3757194Sgblack@eecs.umich.edu 3767194Sgblack@eecs.umich.edu /** 3777194Sgblack@eecs.umich.edu * A virtual base opaque structure used to hold state associated 3787194Sgblack@eecs.umich.edu * with the packet (e.g., an MSHR), specific to a MemObject that 3797194Sgblack@eecs.umich.edu * sees the packet. A pointer to this state is returned in the 3807194Sgblack@eecs.umich.edu * packet's response so that the MemObject in question can quickly 3817194Sgblack@eecs.umich.edu * look up the state needed to process it. A specific subclass 3827231Sgblack@eecs.umich.edu * would be derived from this to carry state specific to a 3837194Sgblack@eecs.umich.edu * particular sending device. 3847231Sgblack@eecs.umich.edu * 3857194Sgblack@eecs.umich.edu * As multiple MemObjects may add their SenderState throughout the 3867231Sgblack@eecs.umich.edu * memory system, the SenderStates create a stack, where a 3877194Sgblack@eecs.umich.edu * MemObject can add a new Senderstate, as long as the 3887231Sgblack@eecs.umich.edu * predecessing SenderState is restored when the response comes 3897194Sgblack@eecs.umich.edu * back. For this reason, the predecessor should always be 3907231Sgblack@eecs.umich.edu * populated with the current SenderState of a packet before 3917194Sgblack@eecs.umich.edu * modifying the senderState field in the request packet. 3927231Sgblack@eecs.umich.edu */ 3937194Sgblack@eecs.umich.edu struct SenderState 3947194Sgblack@eecs.umich.edu { 3957194Sgblack@eecs.umich.edu SenderState* predecessor; 3967194Sgblack@eecs.umich.edu SenderState() : predecessor(NULL) {} 3977194Sgblack@eecs.umich.edu virtual ~SenderState() {} 3987194Sgblack@eecs.umich.edu }; 3997194Sgblack@eecs.umich.edu 4007194Sgblack@eecs.umich.edu /** 4017222Sgblack@eecs.umich.edu * Object used to maintain state of a PrintReq. The senderState 4027194Sgblack@eecs.umich.edu * field of a PrintReq should always be of this type. 4037222Sgblack@eecs.umich.edu */ 4047194Sgblack@eecs.umich.edu class PrintReqState : public SenderState 4057222Sgblack@eecs.umich.edu { 4067194Sgblack@eecs.umich.edu private: 4077222Sgblack@eecs.umich.edu /** 4087194Sgblack@eecs.umich.edu * An entry in the label stack. 4097222Sgblack@eecs.umich.edu */ 4107194Sgblack@eecs.umich.edu struct LabelStackEntry 4117222Sgblack@eecs.umich.edu { 4127194Sgblack@eecs.umich.edu const std::string label; 4137194Sgblack@eecs.umich.edu std::string *prefix; 4147194Sgblack@eecs.umich.edu bool labelPrinted; 4157194Sgblack@eecs.umich.edu LabelStackEntry(const std::string &_label, std::string *_prefix); 4167194Sgblack@eecs.umich.edu }; 4177220Sgblack@eecs.umich.edu 4187194Sgblack@eecs.umich.edu typedef std::list<LabelStackEntry> LabelStack; 4197220Sgblack@eecs.umich.edu LabelStack labelStack; 4207194Sgblack@eecs.umich.edu 4217220Sgblack@eecs.umich.edu std::string *curPrefixPtr; 4227194Sgblack@eecs.umich.edu 4237220Sgblack@eecs.umich.edu public: 4247194Sgblack@eecs.umich.edu std::ostream &os; 4257220Sgblack@eecs.umich.edu const int verbosity; 4267194Sgblack@eecs.umich.edu 4277220Sgblack@eecs.umich.edu PrintReqState(std::ostream &os, int verbosity = 0); 4287194Sgblack@eecs.umich.edu ~PrintReqState(); 4297194Sgblack@eecs.umich.edu 4307194Sgblack@eecs.umich.edu /** 4317194Sgblack@eecs.umich.edu * Returns the current line prefix. 4327194Sgblack@eecs.umich.edu */ 4337231Sgblack@eecs.umich.edu const std::string &curPrefix() { return *curPrefixPtr; } 4347194Sgblack@eecs.umich.edu 4357231Sgblack@eecs.umich.edu /** 4367194Sgblack@eecs.umich.edu * Push a label onto the label stack, and prepend the given 4377231Sgblack@eecs.umich.edu * prefix string onto the current prefix. Labels will only be 4387194Sgblack@eecs.umich.edu * printed if an object within the label's scope is printed. 4397231Sgblack@eecs.umich.edu */ 4407194Sgblack@eecs.umich.edu void pushLabel(const std::string &lbl, 4417231Sgblack@eecs.umich.edu const std::string &prefix = " "); 4427194Sgblack@eecs.umich.edu 4437231Sgblack@eecs.umich.edu /** 4447194Sgblack@eecs.umich.edu * Pop a label off the label stack. 4457194Sgblack@eecs.umich.edu */ 4467194Sgblack@eecs.umich.edu void popLabel(); 4477194Sgblack@eecs.umich.edu 4487194Sgblack@eecs.umich.edu /** 4497194Sgblack@eecs.umich.edu * Print all of the pending unprinted labels on the 4507194Sgblack@eecs.umich.edu * stack. Called by printObj(), so normally not called by 4517194Sgblack@eecs.umich.edu * users unless bypassing printObj(). 4527194Sgblack@eecs.umich.edu */ 4537139Sgblack@eecs.umich.edu void printLabels(); 4547188Sgblack@eecs.umich.edu 4557188Sgblack@eecs.umich.edu /** 4567188Sgblack@eecs.umich.edu * Print a Printable object to os, because it matched the 4577188Sgblack@eecs.umich.edu * address on a PrintReq. 4587188Sgblack@eecs.umich.edu */ 4597188Sgblack@eecs.umich.edu void printObj(Printable *obj); 4607188Sgblack@eecs.umich.edu }; 4617188Sgblack@eecs.umich.edu 4627139Sgblack@eecs.umich.edu /** 4637188Sgblack@eecs.umich.edu * This packet's sender state. Devices should use dynamic_cast<> 4647139Sgblack@eecs.umich.edu * to cast to the state appropriate to the sender. The intent of 4657188Sgblack@eecs.umich.edu * this variable is to allow a device to attach extra information 4667188Sgblack@eecs.umich.edu * to a request. A response packet must return the sender state 4677188Sgblack@eecs.umich.edu * that was attached to the original request (even if a new packet 4687188Sgblack@eecs.umich.edu * is created). 4697188Sgblack@eecs.umich.edu */ 4707188Sgblack@eecs.umich.edu SenderState *senderState; 4717139Sgblack@eecs.umich.edu 4727188Sgblack@eecs.umich.edu /** 4737188Sgblack@eecs.umich.edu * Push a new sender state to the packet and make the current 4747188Sgblack@eecs.umich.edu * sender state the predecessor of the new one. This should be 4757188Sgblack@eecs.umich.edu * prefered over direct manipulation of the senderState member 4767188Sgblack@eecs.umich.edu * variable. 4777188Sgblack@eecs.umich.edu * 4787139Sgblack@eecs.umich.edu * @param sender_state SenderState to push at the top of the stack 4797139Sgblack@eecs.umich.edu */ 4807139Sgblack@eecs.umich.edu void pushSenderState(SenderState *sender_state); 4817139Sgblack@eecs.umich.edu 4827188Sgblack@eecs.umich.edu /** 4837188Sgblack@eecs.umich.edu * Pop the top of the state stack and return a pointer to it. This 4847188Sgblack@eecs.umich.edu * assumes the current sender state is not NULL. This should be 4857188Sgblack@eecs.umich.edu * preferred over direct manipulation of the senderState member 4867188Sgblack@eecs.umich.edu * variable. 4877188Sgblack@eecs.umich.edu * 4887188Sgblack@eecs.umich.edu * @return The current top of the stack 4897188Sgblack@eecs.umich.edu */ 4907188Sgblack@eecs.umich.edu SenderState *popSenderState(); 4917188Sgblack@eecs.umich.edu 4927188Sgblack@eecs.umich.edu /** 4937188Sgblack@eecs.umich.edu * Go through the sender state stack and return the first instance 4947188Sgblack@eecs.umich.edu * that is of type T (as determined by a dynamic_cast). If there 4957188Sgblack@eecs.umich.edu * is no sender state of type T, NULL is returned. 4967188Sgblack@eecs.umich.edu * 4977188Sgblack@eecs.umich.edu * @return The topmost state of type T 4987188Sgblack@eecs.umich.edu */ 4997188Sgblack@eecs.umich.edu template <typename T> 5007188Sgblack@eecs.umich.edu T * findNextSenderState() const 5017188Sgblack@eecs.umich.edu { 5027188Sgblack@eecs.umich.edu T *t = NULL; 5037188Sgblack@eecs.umich.edu SenderState* sender_state = senderState; 5047188Sgblack@eecs.umich.edu while (t == NULL && sender_state != NULL) { 5057185Sgblack@eecs.umich.edu t = dynamic_cast<T*>(sender_state); 5067188Sgblack@eecs.umich.edu sender_state = sender_state->predecessor; 5077188Sgblack@eecs.umich.edu } 5087188Sgblack@eecs.umich.edu return t; 5097188Sgblack@eecs.umich.edu } 5107188Sgblack@eecs.umich.edu 5117188Sgblack@eecs.umich.edu /// Return the string name of the cmd field (for debugging and 5127188Sgblack@eecs.umich.edu /// tracing). 5137188Sgblack@eecs.umich.edu const std::string &cmdString() const { return cmd.toString(); } 5147188Sgblack@eecs.umich.edu 5157188Sgblack@eecs.umich.edu /// Return the index of this command. 5167188Sgblack@eecs.umich.edu inline int cmdToIndex() const { return cmd.toInt(); } 5177188Sgblack@eecs.umich.edu 5187139Sgblack@eecs.umich.edu bool isRead() const { return cmd.isRead(); } 5197139Sgblack@eecs.umich.edu bool isWrite() const { return cmd.isWrite(); } 5207139Sgblack@eecs.umich.edu bool isUpgrade() const { return cmd.isUpgrade(); } 5217139Sgblack@eecs.umich.edu bool isRequest() const { return cmd.isRequest(); } 5227139Sgblack@eecs.umich.edu bool isResponse() const { return cmd.isResponse(); } 5237139Sgblack@eecs.umich.edu bool needsWritable() const 5247139Sgblack@eecs.umich.edu { 5257139Sgblack@eecs.umich.edu // we should never check if a response needsWritable, the 5267139Sgblack@eecs.umich.edu // request has this flag, and for a response we should rather 5277139Sgblack@eecs.umich.edu // look at the hasSharers flag (if not set, the response is to 5287139Sgblack@eecs.umich.edu // be considered writable) 5297139Sgblack@eecs.umich.edu assert(isRequest()); 5307139Sgblack@eecs.umich.edu return cmd.needsWritable(); 5317139Sgblack@eecs.umich.edu } 5327185Sgblack@eecs.umich.edu bool needsResponse() const { return cmd.needsResponse(); } 5337139Sgblack@eecs.umich.edu bool isInvalidate() const { return cmd.isInvalidate(); } 5347185Sgblack@eecs.umich.edu bool isEviction() const { return cmd.isEviction(); } 5357139Sgblack@eecs.umich.edu bool isClean() const { return cmd.isClean(); } 5367139Sgblack@eecs.umich.edu bool fromCache() const { return cmd.fromCache(); } 5377139Sgblack@eecs.umich.edu bool isWriteback() const { return cmd.isWriteback(); } 5387188Sgblack@eecs.umich.edu bool hasData() const { return cmd.hasData(); } 5397188Sgblack@eecs.umich.edu bool hasRespData() const 5407188Sgblack@eecs.umich.edu { 5417188Sgblack@eecs.umich.edu MemCmd resp_cmd = cmd.responseCommand(); 5427139Sgblack@eecs.umich.edu return resp_cmd.hasData(); 5437188Sgblack@eecs.umich.edu } 5447139Sgblack@eecs.umich.edu bool isLLSC() const { return cmd.isLLSC(); } 5457188Sgblack@eecs.umich.edu bool isError() const { return cmd.isError(); } 5467139Sgblack@eecs.umich.edu bool isPrint() const { return cmd.isPrint(); } 5477139Sgblack@eecs.umich.edu bool isFlush() const { return cmd.isFlush(); } 5487139Sgblack@eecs.umich.edu 5497139Sgblack@eecs.umich.edu //@{ 5507139Sgblack@eecs.umich.edu /// Snoop flags 5517139Sgblack@eecs.umich.edu /** 5527139Sgblack@eecs.umich.edu * Set the cacheResponding flag. This is used by the caches to 5537141Sgblack@eecs.umich.edu * signal another cache that they are responding to a request. A 5547195Sgblack@eecs.umich.edu * cache will only respond to snoops if it has the line in either 5557195Sgblack@eecs.umich.edu * Modified or Owned state. Note that on snoop hits we always pass 5567195Sgblack@eecs.umich.edu * the line as Modified and never Owned. In the case of an Owned 5577195Sgblack@eecs.umich.edu * line we proceed to invalidate all other copies. 5587195Sgblack@eecs.umich.edu * 5597195Sgblack@eecs.umich.edu * On a cache fill (see Cache::handleFill), we check hasSharers 5607195Sgblack@eecs.umich.edu * first, ignoring the cacheResponding flag if hasSharers is set. 5617195Sgblack@eecs.umich.edu * A line is consequently allocated as: 5627195Sgblack@eecs.umich.edu * 5637195Sgblack@eecs.umich.edu * hasSharers cacheResponding state 5647195Sgblack@eecs.umich.edu * true false Shared 5657195Sgblack@eecs.umich.edu * true true Shared 5667195Sgblack@eecs.umich.edu * false false Exclusive 5677195Sgblack@eecs.umich.edu * false true Modified 5687195Sgblack@eecs.umich.edu */ 5697195Sgblack@eecs.umich.edu void setCacheResponding() 5707195Sgblack@eecs.umich.edu { 5717195Sgblack@eecs.umich.edu assert(isRequest()); 5727195Sgblack@eecs.umich.edu assert(!flags.isSet(CACHE_RESPONDING)); 5737195Sgblack@eecs.umich.edu flags.set(CACHE_RESPONDING); 5747195Sgblack@eecs.umich.edu } 5757195Sgblack@eecs.umich.edu bool cacheResponding() const { return flags.isSet(CACHE_RESPONDING); } 5767213Sgblack@eecs.umich.edu /** 5777213Sgblack@eecs.umich.edu * On fills, the hasSharers flag is used by the caches in 5787213Sgblack@eecs.umich.edu * combination with the cacheResponding flag, as clarified 5797213Sgblack@eecs.umich.edu * above. If the hasSharers flag is not set, the packet is passing 5807213Sgblack@eecs.umich.edu * writable. Thus, a response from a memory passes the line as 5817213Sgblack@eecs.umich.edu * writable by default. 5827290Sgblack@eecs.umich.edu * 5837290Sgblack@eecs.umich.edu * The hasSharers flag is also used by upstream caches to inform a 5847290Sgblack@eecs.umich.edu * downstream cache that they have the block (by calling 5857213Sgblack@eecs.umich.edu * setHasSharers on snoop request packets that hit in upstream 5867213Sgblack@eecs.umich.edu * cachs tags or MSHRs). If the snoop packet has sharers, a 5877213Sgblack@eecs.umich.edu * downstream cache is prevented from passing a dirty line upwards 5887213Sgblack@eecs.umich.edu * if it was not explicitly asked for a writable copy. See 5897213Sgblack@eecs.umich.edu * Cache::satisfyCpuSideRequest. 5907213Sgblack@eecs.umich.edu * 5917213Sgblack@eecs.umich.edu * The hasSharers flag is also used on writebacks, in 5927213Sgblack@eecs.umich.edu * combination with the WritbackClean or WritebackDirty commands, 5937213Sgblack@eecs.umich.edu * to allocate the block downstream either as: 5947213Sgblack@eecs.umich.edu * 5957213Sgblack@eecs.umich.edu * command hasSharers state 5967213Sgblack@eecs.umich.edu * WritebackDirty false Modified 5977213Sgblack@eecs.umich.edu * WritebackDirty true Owned 5987213Sgblack@eecs.umich.edu * WritebackClean false Exclusive 5997213Sgblack@eecs.umich.edu * WritebackClean true Shared 6007213Sgblack@eecs.umich.edu */ 6017213Sgblack@eecs.umich.edu void setHasSharers() { flags.set(HAS_SHARERS); } 6027213Sgblack@eecs.umich.edu bool hasSharers() const { return flags.isSet(HAS_SHARERS); } 6037213Sgblack@eecs.umich.edu //@} 6047213Sgblack@eecs.umich.edu 6057213Sgblack@eecs.umich.edu /** 6067213Sgblack@eecs.umich.edu * The express snoop flag is used for two purposes. Firstly, it is 6077213Sgblack@eecs.umich.edu * used to bypass flow control for normal (non-snoop) requests 6087213Sgblack@eecs.umich.edu * going downstream in the memory system. In cases where a cache 6097213Sgblack@eecs.umich.edu * is responding to a snoop from another cache (it had a dirty 6107213Sgblack@eecs.umich.edu * line), but the line is not writable (and there are possibly 6117213Sgblack@eecs.umich.edu * other copies), the express snoop flag is set by the downstream 6127213Sgblack@eecs.umich.edu * cache to invalidate all other copies in zero time. Secondly, 6137213Sgblack@eecs.umich.edu * the express snoop flag is also set to be able to distinguish 6147213Sgblack@eecs.umich.edu * snoop packets that came from a downstream cache, rather than 6157290Sgblack@eecs.umich.edu * snoop packets from neighbouring caches. 6167290Sgblack@eecs.umich.edu */ 6177290Sgblack@eecs.umich.edu void setExpressSnoop() { flags.set(EXPRESS_SNOOP); } 6187235Sgblack@eecs.umich.edu bool isExpressSnoop() const { return flags.isSet(EXPRESS_SNOOP); } 6197235Sgblack@eecs.umich.edu 6207235Sgblack@eecs.umich.edu /** 6217235Sgblack@eecs.umich.edu * On responding to a snoop request (which only happens for 6227235Sgblack@eecs.umich.edu * Modified or Owned lines), make sure that we can transform an 6237235Sgblack@eecs.umich.edu * Owned response to a Modified one. If this flag is not set, the 6247235Sgblack@eecs.umich.edu * responding cache had the line in the Owned state, and there are 6257235Sgblack@eecs.umich.edu * possibly other Shared copies in the memory system. A downstream 6267235Sgblack@eecs.umich.edu * cache helps in orchestrating the invalidation of these copies 6277235Sgblack@eecs.umich.edu * by sending out the appropriate express snoops. 6287235Sgblack@eecs.umich.edu */ 6297235Sgblack@eecs.umich.edu void setResponderHadWritable() 6307235Sgblack@eecs.umich.edu { 6317235Sgblack@eecs.umich.edu assert(cacheResponding()); 6327235Sgblack@eecs.umich.edu assert(!responderHadWritable()); 6337235Sgblack@eecs.umich.edu flags.set(RESPONDER_HAD_WRITABLE); 6347235Sgblack@eecs.umich.edu } 6357235Sgblack@eecs.umich.edu bool responderHadWritable() const 6367235Sgblack@eecs.umich.edu { return flags.isSet(RESPONDER_HAD_WRITABLE); } 6377235Sgblack@eecs.umich.edu 6387235Sgblack@eecs.umich.edu /** 6397235Sgblack@eecs.umich.edu * A writeback/writeclean cmd gets propagated further downstream 6407235Sgblack@eecs.umich.edu * by the receiver when the flag is set. 6417235Sgblack@eecs.umich.edu */ 6427235Sgblack@eecs.umich.edu void setWriteThrough() 6437235Sgblack@eecs.umich.edu { 6447235Sgblack@eecs.umich.edu assert(cmd.isWrite() && 6457235Sgblack@eecs.umich.edu (cmd.isEviction() || cmd == MemCmd::WriteClean)); 6467235Sgblack@eecs.umich.edu flags.set(WRITE_THROUGH); 6477235Sgblack@eecs.umich.edu } 6487235Sgblack@eecs.umich.edu void clearWriteThrough() { flags.clear(WRITE_THROUGH); } 6497235Sgblack@eecs.umich.edu bool writeThrough() const { return flags.isSet(WRITE_THROUGH); } 6507235Sgblack@eecs.umich.edu 6517235Sgblack@eecs.umich.edu /** 6527235Sgblack@eecs.umich.edu * Set when a request hits in a cache and the cache is not going 6537235Sgblack@eecs.umich.edu * to respond. This is used by the crossbar to coordinate 6547235Sgblack@eecs.umich.edu * responses for cache maintenance operations. 6557235Sgblack@eecs.umich.edu */ 6567235Sgblack@eecs.umich.edu void setSatisfied() 6577235Sgblack@eecs.umich.edu { 6587235Sgblack@eecs.umich.edu assert(cmd.isClean()); 6597235Sgblack@eecs.umich.edu assert(!flags.isSet(SATISFIED)); 6607235Sgblack@eecs.umich.edu flags.set(SATISFIED); 6617235Sgblack@eecs.umich.edu } 6627235Sgblack@eecs.umich.edu bool satisfied() const { return flags.isSet(SATISFIED); } 6637213Sgblack@eecs.umich.edu 6647213Sgblack@eecs.umich.edu void setSuppressFuncError() { flags.set(SUPPRESS_FUNC_ERROR); } 6657213Sgblack@eecs.umich.edu bool suppressFuncError() const { return flags.isSet(SUPPRESS_FUNC_ERROR); } 6667213Sgblack@eecs.umich.edu void setBlockCached() { flags.set(BLOCK_CACHED); } 6677220Sgblack@eecs.umich.edu bool isBlockCached() const { return flags.isSet(BLOCK_CACHED); } 6687220Sgblack@eecs.umich.edu void clearBlockCached() { flags.clear(BLOCK_CACHED); } 6697220Sgblack@eecs.umich.edu 6707220Sgblack@eecs.umich.edu // Network error conditions... encapsulate them as methods since 6717213Sgblack@eecs.umich.edu // their encoding keeps changing (from result field to command 6727213Sgblack@eecs.umich.edu // field, etc.) 6737213Sgblack@eecs.umich.edu void 6747213Sgblack@eecs.umich.edu setBadAddress() 6757213Sgblack@eecs.umich.edu { 6767213Sgblack@eecs.umich.edu assert(isResponse()); 6777213Sgblack@eecs.umich.edu cmd = MemCmd::BadAddressError; 6787216Sgblack@eecs.umich.edu } 6797216Sgblack@eecs.umich.edu 6807213Sgblack@eecs.umich.edu void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; } 6817224Sgblack@eecs.umich.edu 6827224Sgblack@eecs.umich.edu Addr getAddr() const { assert(flags.isSet(VALID_ADDR)); return addr; } 6837213Sgblack@eecs.umich.edu /** 6847224Sgblack@eecs.umich.edu * Update the address of this packet mid-transaction. This is used 6857224Sgblack@eecs.umich.edu * by the address mapper to change an already set address to a new 6867213Sgblack@eecs.umich.edu * one based on the system configuration. It is intended to remap 6877218Sgblack@eecs.umich.edu * an existing address, so it asserts that the current address is 6887218Sgblack@eecs.umich.edu * valid. 6897213Sgblack@eecs.umich.edu */ 6907216Sgblack@eecs.umich.edu void setAddr(Addr _addr) { assert(flags.isSet(VALID_ADDR)); addr = _addr; } 6917216Sgblack@eecs.umich.edu 6927213Sgblack@eecs.umich.edu unsigned getSize() const { assert(flags.isSet(VALID_SIZE)); return size; } 6937218Sgblack@eecs.umich.edu 6947218Sgblack@eecs.umich.edu Addr getOffset(unsigned int blk_size) const 6957213Sgblack@eecs.umich.edu { 6967213Sgblack@eecs.umich.edu return getAddr() & Addr(blk_size - 1); 6977213Sgblack@eecs.umich.edu } 6987216Sgblack@eecs.umich.edu 6997216Sgblack@eecs.umich.edu Addr getBlockAddr(unsigned int blk_size) const 7007216Sgblack@eecs.umich.edu { 7017216Sgblack@eecs.umich.edu return getAddr() & ~(Addr(blk_size - 1)); 7027216Sgblack@eecs.umich.edu } 7037216Sgblack@eecs.umich.edu 7047216Sgblack@eecs.umich.edu bool isSecure() const 7057216Sgblack@eecs.umich.edu { 7067216Sgblack@eecs.umich.edu assert(flags.isSet(VALID_ADDR)); 7077216Sgblack@eecs.umich.edu return _isSecure; 7087216Sgblack@eecs.umich.edu } 7097216Sgblack@eecs.umich.edu 7107216Sgblack@eecs.umich.edu /** 7117213Sgblack@eecs.umich.edu * Accessor function to atomic op. 7127213Sgblack@eecs.umich.edu */ 7137213Sgblack@eecs.umich.edu AtomicOpFunctor *getAtomicOp() const { return req->getAtomicOpFunctor(); } 7147213Sgblack@eecs.umich.edu bool isAtomicOp() const { return req->isAtomic(); } 7157213Sgblack@eecs.umich.edu 7167231Sgblack@eecs.umich.edu /** 7177213Sgblack@eecs.umich.edu * It has been determined that the SC packet should successfully update 7187231Sgblack@eecs.umich.edu * memory. Therefore, convert this SC packet to a normal write. 7197213Sgblack@eecs.umich.edu */ 7207231Sgblack@eecs.umich.edu void 7217213Sgblack@eecs.umich.edu convertScToWrite() 7227231Sgblack@eecs.umich.edu { 7237213Sgblack@eecs.umich.edu assert(isLLSC()); 7247231Sgblack@eecs.umich.edu assert(isWrite()); 7257213Sgblack@eecs.umich.edu cmd = MemCmd::WriteReq; 7267231Sgblack@eecs.umich.edu } 7277213Sgblack@eecs.umich.edu 7287213Sgblack@eecs.umich.edu /** 7297213Sgblack@eecs.umich.edu * When ruby is in use, Ruby will monitor the cache line and the 7307213Sgblack@eecs.umich.edu * phys memory should treat LL ops as normal reads. 7317213Sgblack@eecs.umich.edu */ 7327213Sgblack@eecs.umich.edu void 7337213Sgblack@eecs.umich.edu convertLlToRead() 7347213Sgblack@eecs.umich.edu { 7357213Sgblack@eecs.umich.edu assert(isLLSC()); 7367213Sgblack@eecs.umich.edu assert(isRead()); 7377222Sgblack@eecs.umich.edu cmd = MemCmd::ReadReq; 7387222Sgblack@eecs.umich.edu } 7397213Sgblack@eecs.umich.edu 7407222Sgblack@eecs.umich.edu /** 7417222Sgblack@eecs.umich.edu * Constructor. Note that a Request object must be constructed 7427213Sgblack@eecs.umich.edu * first, but the Requests's physical address and size fields need 7437222Sgblack@eecs.umich.edu * not be valid. The command must be supplied. 7447222Sgblack@eecs.umich.edu */ 7457213Sgblack@eecs.umich.edu Packet(const RequestPtr _req, MemCmd _cmd) 7467222Sgblack@eecs.umich.edu : cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false), 7477222Sgblack@eecs.umich.edu size(0), headerDelay(0), snoopDelay(0), payloadDelay(0), 7487213Sgblack@eecs.umich.edu senderState(NULL) 7497222Sgblack@eecs.umich.edu { 7507222Sgblack@eecs.umich.edu if (req->hasPaddr()) { 7517213Sgblack@eecs.umich.edu addr = req->getPaddr(); 7527222Sgblack@eecs.umich.edu flags.set(VALID_ADDR); 7537222Sgblack@eecs.umich.edu _isSecure = req->isSecure(); 7547213Sgblack@eecs.umich.edu } 7557213Sgblack@eecs.umich.edu if (req->hasSize()) { 7567213Sgblack@eecs.umich.edu size = req->getSize(); 7577213Sgblack@eecs.umich.edu flags.set(VALID_SIZE); 7587213Sgblack@eecs.umich.edu } 7597220Sgblack@eecs.umich.edu } 7607213Sgblack@eecs.umich.edu 7617220Sgblack@eecs.umich.edu /** 7627213Sgblack@eecs.umich.edu * Alternate constructor if you are trying to create a packet with 7637220Sgblack@eecs.umich.edu * a request that is for a whole block, not the address from the 7647213Sgblack@eecs.umich.edu * req. this allows for overriding the size/addr of the req. 7657220Sgblack@eecs.umich.edu */ 7667213Sgblack@eecs.umich.edu Packet(const RequestPtr _req, MemCmd _cmd, int _blkSize) 7677220Sgblack@eecs.umich.edu : cmd(_cmd), req(_req), data(nullptr), addr(0), _isSecure(false), 7687213Sgblack@eecs.umich.edu headerDelay(0), snoopDelay(0), payloadDelay(0), 7697220Sgblack@eecs.umich.edu senderState(NULL) 7707213Sgblack@eecs.umich.edu { 7717213Sgblack@eecs.umich.edu if (req->hasPaddr()) { 7727213Sgblack@eecs.umich.edu addr = req->getPaddr() & ~(_blkSize - 1); 7737213Sgblack@eecs.umich.edu flags.set(VALID_ADDR); 7747213Sgblack@eecs.umich.edu _isSecure = req->isSecure(); 7757231Sgblack@eecs.umich.edu } 7767213Sgblack@eecs.umich.edu size = _blkSize; 7777231Sgblack@eecs.umich.edu flags.set(VALID_SIZE); 7787213Sgblack@eecs.umich.edu } 7797231Sgblack@eecs.umich.edu 7807213Sgblack@eecs.umich.edu /** 7817231Sgblack@eecs.umich.edu * Alternate constructor for copying a packet. Copy all fields 7827213Sgblack@eecs.umich.edu * *except* if the original packet's data was dynamic, don't copy 7837231Sgblack@eecs.umich.edu * that, as we can't guarantee that the new packet's lifetime is 7847213Sgblack@eecs.umich.edu * less than that of the original packet. In this case the new 7857231Sgblack@eecs.umich.edu * packet should allocate its own data. 7867213Sgblack@eecs.umich.edu */ 7877213Sgblack@eecs.umich.edu Packet(const PacketPtr pkt, bool clear_flags, bool alloc_data) 7887213Sgblack@eecs.umich.edu : cmd(pkt->cmd), req(pkt->req), 7897213Sgblack@eecs.umich.edu data(nullptr), 7907213Sgblack@eecs.umich.edu addr(pkt->addr), _isSecure(pkt->_isSecure), size(pkt->size), 7917213Sgblack@eecs.umich.edu bytesValid(pkt->bytesValid), 7927213Sgblack@eecs.umich.edu headerDelay(pkt->headerDelay), 7937240Sgblack@eecs.umich.edu snoopDelay(0), 7947240Sgblack@eecs.umich.edu payloadDelay(pkt->payloadDelay), 7957240Sgblack@eecs.umich.edu senderState(pkt->senderState) 7967240Sgblack@eecs.umich.edu { 7977213Sgblack@eecs.umich.edu if (!clear_flags) 7987213Sgblack@eecs.umich.edu flags.set(pkt->flags & COPY_FLAGS); 7997240Sgblack@eecs.umich.edu 8007240Sgblack@eecs.umich.edu flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE)); 8017240Sgblack@eecs.umich.edu 8027240Sgblack@eecs.umich.edu // should we allocate space for data, or not, the express 8037240Sgblack@eecs.umich.edu // snoops do not need to carry any data as they only serve to 8047240Sgblack@eecs.umich.edu // co-ordinate state changes 8057240Sgblack@eecs.umich.edu if (alloc_data) { 8067240Sgblack@eecs.umich.edu // even if asked to allocate data, if the original packet 8077240Sgblack@eecs.umich.edu // holds static data, then the sender will not be doing 8087240Sgblack@eecs.umich.edu // any memcpy on receiving the response, thus we simply 8097240Sgblack@eecs.umich.edu // carry the pointer forward 8107240Sgblack@eecs.umich.edu if (pkt->flags.isSet(STATIC_DATA)) { 8117240Sgblack@eecs.umich.edu data = pkt->data; 8127213Sgblack@eecs.umich.edu flags.set(STATIC_DATA); 8137213Sgblack@eecs.umich.edu } else { 8147213Sgblack@eecs.umich.edu allocate(); 8157240Sgblack@eecs.umich.edu } 8167240Sgblack@eecs.umich.edu } 8177240Sgblack@eecs.umich.edu } 8187240Sgblack@eecs.umich.edu 8197240Sgblack@eecs.umich.edu /** 8207240Sgblack@eecs.umich.edu * Generate the appropriate read MemCmd based on the Request flags. 8217250Sgblack@eecs.umich.edu */ 8227240Sgblack@eecs.umich.edu static MemCmd 8237240Sgblack@eecs.umich.edu makeReadCmd(const RequestPtr req) 8247213Sgblack@eecs.umich.edu { 8257213Sgblack@eecs.umich.edu if (req->isLLSC()) 8267213Sgblack@eecs.umich.edu return MemCmd::LoadLockedReq; 8277213Sgblack@eecs.umich.edu else if (req->isPrefetch()) 8287240Sgblack@eecs.umich.edu return MemCmd::SoftPFReq; 8297213Sgblack@eecs.umich.edu else 8307213Sgblack@eecs.umich.edu return MemCmd::ReadReq; 8317213Sgblack@eecs.umich.edu } 8327213Sgblack@eecs.umich.edu 8337252Sgblack@eecs.umich.edu /** 8347213Sgblack@eecs.umich.edu * Generate the appropriate write MemCmd based on the Request flags. 8357213Sgblack@eecs.umich.edu */ 8367213Sgblack@eecs.umich.edu static MemCmd 8377213Sgblack@eecs.umich.edu makeWriteCmd(const RequestPtr req) 8387213Sgblack@eecs.umich.edu { 8397213Sgblack@eecs.umich.edu if (req->isLLSC()) 8407213Sgblack@eecs.umich.edu return MemCmd::StoreCondReq; 8417213Sgblack@eecs.umich.edu else if (req->isSwap()) 8427213Sgblack@eecs.umich.edu return MemCmd::SwapReq; 8437141Sgblack@eecs.umich.edu else if (req->isCacheInvalidate()) { 8447141Sgblack@eecs.umich.edu return req->isCacheClean() ? MemCmd::CleanInvalidReq : 8457141Sgblack@eecs.umich.edu MemCmd::InvalidateReq; 8467141Sgblack@eecs.umich.edu } else if (req->isCacheClean()) { 8477141Sgblack@eecs.umich.edu return MemCmd::CleanSharedReq; 8487141Sgblack@eecs.umich.edu } else 8497141Sgblack@eecs.umich.edu return MemCmd::WriteReq; 8507141Sgblack@eecs.umich.edu } 8517141Sgblack@eecs.umich.edu 8527141Sgblack@eecs.umich.edu /** 8537141Sgblack@eecs.umich.edu * Constructor-like methods that return Packets based on Request objects. 8547141Sgblack@eecs.umich.edu * Fine-tune the MemCmd type if it's not a vanilla read or write. 8557408Sgblack@eecs.umich.edu */ 8567408Sgblack@eecs.umich.edu static PacketPtr 8577408Sgblack@eecs.umich.edu createRead(const RequestPtr req) 8587408Sgblack@eecs.umich.edu { 8597408Sgblack@eecs.umich.edu return new Packet(req, makeReadCmd(req)); 8607141Sgblack@eecs.umich.edu } 8617408Sgblack@eecs.umich.edu 8627408Sgblack@eecs.umich.edu static PacketPtr 8637408Sgblack@eecs.umich.edu createWrite(const RequestPtr req) 8647408Sgblack@eecs.umich.edu { 8657408Sgblack@eecs.umich.edu return new Packet(req, makeWriteCmd(req)); 8667141Sgblack@eecs.umich.edu } 8677408Sgblack@eecs.umich.edu 8687408Sgblack@eecs.umich.edu /** 8697408Sgblack@eecs.umich.edu * clean up packet variables 8707408Sgblack@eecs.umich.edu */ 8717408Sgblack@eecs.umich.edu ~Packet() 8727141Sgblack@eecs.umich.edu { 8737141Sgblack@eecs.umich.edu // Delete the request object if this is a request packet which 8747141Sgblack@eecs.umich.edu // does not need a response, because the requester will not get 8757408Sgblack@eecs.umich.edu // a chance. If the request packet needs a response then the 8767408Sgblack@eecs.umich.edu // request will be deleted on receipt of the response 8777408Sgblack@eecs.umich.edu // packet. We also make sure to never delete the request for 8787408Sgblack@eecs.umich.edu // express snoops, even for cases when responses are not 8797408Sgblack@eecs.umich.edu // needed (CleanEvict and Writeback), since the snoop packet 8807141Sgblack@eecs.umich.edu // re-uses the same request. 8817408Sgblack@eecs.umich.edu if (req && isRequest() && !needsResponse() && 8827408Sgblack@eecs.umich.edu !isExpressSnoop()) { 8837408Sgblack@eecs.umich.edu delete req; 8847408Sgblack@eecs.umich.edu } 8857408Sgblack@eecs.umich.edu deleteData(); 8867141Sgblack@eecs.umich.edu } 8877408Sgblack@eecs.umich.edu 8887408Sgblack@eecs.umich.edu /** 8897408Sgblack@eecs.umich.edu * Take a request packet and modify it in place to be suitable for 8907408Sgblack@eecs.umich.edu * returning as a response to that request. 8917408Sgblack@eecs.umich.edu */ 8927141Sgblack@eecs.umich.edu void 8937408Sgblack@eecs.umich.edu makeResponse() 8947408Sgblack@eecs.umich.edu { 8957408Sgblack@eecs.umich.edu assert(needsResponse()); 8967408Sgblack@eecs.umich.edu assert(isRequest()); 8977408Sgblack@eecs.umich.edu cmd = cmd.responseCommand(); 8987141Sgblack@eecs.umich.edu 8997141Sgblack@eecs.umich.edu // responses are never express, even if the snoop that 9007408Sgblack@eecs.umich.edu // triggered them was 9017408Sgblack@eecs.umich.edu flags.clear(EXPRESS_SNOOP); 9027408Sgblack@eecs.umich.edu } 9037408Sgblack@eecs.umich.edu 9047408Sgblack@eecs.umich.edu void 9057141Sgblack@eecs.umich.edu makeAtomicResponse() 9067146Sgblack@eecs.umich.edu { 9077141Sgblack@eecs.umich.edu makeResponse(); 9087408Sgblack@eecs.umich.edu } 9097408Sgblack@eecs.umich.edu 9107408Sgblack@eecs.umich.edu void 9117408Sgblack@eecs.umich.edu makeTimingResponse() 9127408Sgblack@eecs.umich.edu { 9137141Sgblack@eecs.umich.edu makeResponse(); 9147408Sgblack@eecs.umich.edu } 9157408Sgblack@eecs.umich.edu 9167408Sgblack@eecs.umich.edu void 9177408Sgblack@eecs.umich.edu setFunctionalResponseStatus(bool success) 9187408Sgblack@eecs.umich.edu { 9197141Sgblack@eecs.umich.edu if (!success) { 9207141Sgblack@eecs.umich.edu if (isWrite()) { 9217141Sgblack@eecs.umich.edu cmd = MemCmd::FunctionalWriteError; 9227141Sgblack@eecs.umich.edu } else { 9237141Sgblack@eecs.umich.edu cmd = MemCmd::FunctionalReadError; 9247141Sgblack@eecs.umich.edu } 9257141Sgblack@eecs.umich.edu } 9267141Sgblack@eecs.umich.edu } 9277141Sgblack@eecs.umich.edu 9287141Sgblack@eecs.umich.edu void 9297141Sgblack@eecs.umich.edu setSize(unsigned size) 9307141Sgblack@eecs.umich.edu { 9317408Sgblack@eecs.umich.edu assert(!flags.isSet(VALID_SIZE)); 9327408Sgblack@eecs.umich.edu 9337408Sgblack@eecs.umich.edu this->size = size; 9347408Sgblack@eecs.umich.edu flags.set(VALID_SIZE); 9357408Sgblack@eecs.umich.edu } 9367141Sgblack@eecs.umich.edu 9377408Sgblack@eecs.umich.edu 9387408Sgblack@eecs.umich.edu public: 9397408Sgblack@eecs.umich.edu /** 9407408Sgblack@eecs.umich.edu * @{ 9417408Sgblack@eecs.umich.edu * @name Data accessor mehtods 9427141Sgblack@eecs.umich.edu */ 9437408Sgblack@eecs.umich.edu 9447408Sgblack@eecs.umich.edu /** 9457408Sgblack@eecs.umich.edu * Set the data pointer to the following value that should not be 9467408Sgblack@eecs.umich.edu * freed. Static data allows us to do a single memcpy even if 9477408Sgblack@eecs.umich.edu * multiple packets are required to get from source to destination 9487408Sgblack@eecs.umich.edu * and back. In essence the pointer is set calling dataStatic on 9497408Sgblack@eecs.umich.edu * the original packet, and whenever this packet is copied and 9507141Sgblack@eecs.umich.edu * forwarded the same pointer is passed on. When a packet 9517408Sgblack@eecs.umich.edu * eventually reaches the destination holding the data, it is 9527408Sgblack@eecs.umich.edu * copied once into the location originally set. On the way back 9537408Sgblack@eecs.umich.edu * to the source, no copies are necessary. 9547408Sgblack@eecs.umich.edu */ 9557408Sgblack@eecs.umich.edu template <typename T> 9567408Sgblack@eecs.umich.edu void 9577408Sgblack@eecs.umich.edu dataStatic(T *p) 9587141Sgblack@eecs.umich.edu { 9597408Sgblack@eecs.umich.edu assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA)); 9607408Sgblack@eecs.umich.edu data = (PacketDataPtr)p; 9617408Sgblack@eecs.umich.edu flags.set(STATIC_DATA); 9627408Sgblack@eecs.umich.edu } 9637408Sgblack@eecs.umich.edu 9647408Sgblack@eecs.umich.edu /** 9657408Sgblack@eecs.umich.edu * Set the data pointer to the following value that should not be 9667141Sgblack@eecs.umich.edu * freed. This version of the function allows the pointer passed 9677408Sgblack@eecs.umich.edu * to us to be const. To avoid issues down the line we cast the 9687408Sgblack@eecs.umich.edu * constness away, the alternative would be to keep both a const 9697408Sgblack@eecs.umich.edu * and non-const data pointer and cleverly choose between 9707408Sgblack@eecs.umich.edu * them. Note that this is only allowed for static data. 9717408Sgblack@eecs.umich.edu */ 9727141Sgblack@eecs.umich.edu template <typename T> 9737408Sgblack@eecs.umich.edu void 9747408Sgblack@eecs.umich.edu dataStaticConst(const T *p) 9757408Sgblack@eecs.umich.edu { 9767408Sgblack@eecs.umich.edu assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA)); 9777408Sgblack@eecs.umich.edu data = const_cast<PacketDataPtr>(p); 9787141Sgblack@eecs.umich.edu flags.set(STATIC_DATA); 9797408Sgblack@eecs.umich.edu } 9807408Sgblack@eecs.umich.edu 9817408Sgblack@eecs.umich.edu /** 9827408Sgblack@eecs.umich.edu * Set the data pointer to a value that should have delete [] 9837408Sgblack@eecs.umich.edu * called on it. Dynamic data is local to this packet, and as the 9847408Sgblack@eecs.umich.edu * packet travels from source to destination, forwarded packets 9857408Sgblack@eecs.umich.edu * will allocate their own data. When a packet reaches the final 9867141Sgblack@eecs.umich.edu * destination it will populate the dynamic data of that specific 9877183Sgblack@eecs.umich.edu * packet, and on the way back towards the source, memcpy will be 9887141Sgblack@eecs.umich.edu * invoked in every step where a new packet was created e.g. in 9897408Sgblack@eecs.umich.edu * the caches. Ultimately when the response reaches the source a 9907408Sgblack@eecs.umich.edu * final memcpy is needed to extract the data from the packet 9917408Sgblack@eecs.umich.edu * before it is deallocated. 9927408Sgblack@eecs.umich.edu */ 9937408Sgblack@eecs.umich.edu template <typename T> 9947141Sgblack@eecs.umich.edu void 9957183Sgblack@eecs.umich.edu dataDynamic(T *p) 9967141Sgblack@eecs.umich.edu { 9977183Sgblack@eecs.umich.edu assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA)); 9987141Sgblack@eecs.umich.edu data = (PacketDataPtr)p; 9997408Sgblack@eecs.umich.edu flags.set(DYNAMIC_DATA); 10007408Sgblack@eecs.umich.edu } 10017408Sgblack@eecs.umich.edu 10027408Sgblack@eecs.umich.edu /** 10037408Sgblack@eecs.umich.edu * get a pointer to the data ptr. 10047141Sgblack@eecs.umich.edu */ 10057408Sgblack@eecs.umich.edu template <typename T> 10067408Sgblack@eecs.umich.edu T* 10077408Sgblack@eecs.umich.edu getPtr() 10087408Sgblack@eecs.umich.edu { 10097408Sgblack@eecs.umich.edu assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA)); 10107141Sgblack@eecs.umich.edu return (T*)data; 10117408Sgblack@eecs.umich.edu } 10127408Sgblack@eecs.umich.edu 10137408Sgblack@eecs.umich.edu template <typename T> 10147408Sgblack@eecs.umich.edu const T* 10157408Sgblack@eecs.umich.edu getConstPtr() const 10167141Sgblack@eecs.umich.edu { 10177408Sgblack@eecs.umich.edu assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA)); 10187408Sgblack@eecs.umich.edu return (const T*)data; 10197408Sgblack@eecs.umich.edu } 10207408Sgblack@eecs.umich.edu 10217408Sgblack@eecs.umich.edu /** 10227141Sgblack@eecs.umich.edu * Get the data in the packet byte swapped from big endian to 10237141Sgblack@eecs.umich.edu * host endian. 10247141Sgblack@eecs.umich.edu */ 10257141Sgblack@eecs.umich.edu template <typename T> 10267141Sgblack@eecs.umich.edu T getBE() const; 10277141Sgblack@eecs.umich.edu 10287141Sgblack@eecs.umich.edu /** 10297141Sgblack@eecs.umich.edu * Get the data in the packet byte swapped from little endian to 10307141Sgblack@eecs.umich.edu * host endian. 10317141Sgblack@eecs.umich.edu */ 10327141Sgblack@eecs.umich.edu template <typename T> 10337141Sgblack@eecs.umich.edu T getLE() const; 10347141Sgblack@eecs.umich.edu 10357141Sgblack@eecs.umich.edu /** 10367146Sgblack@eecs.umich.edu * Get the data in the packet byte swapped from the specified 10377141Sgblack@eecs.umich.edu * endianness. 10387183Sgblack@eecs.umich.edu */ 10397141Sgblack@eecs.umich.edu template <typename T> 10407146Sgblack@eecs.umich.edu T get(ByteOrder endian) const; 10417141Sgblack@eecs.umich.edu 10427154Sgblack@eecs.umich.edu /** 10437154Sgblack@eecs.umich.edu * Get the data in the packet byte swapped from guest to host 10447154Sgblack@eecs.umich.edu * endian. 10457154Sgblack@eecs.umich.edu */ 10467154Sgblack@eecs.umich.edu template <typename T> 10477154Sgblack@eecs.umich.edu T get() const; 10487154Sgblack@eecs.umich.edu 10497154Sgblack@eecs.umich.edu /** Set the value in the data pointer to v as big endian. */ 10507154Sgblack@eecs.umich.edu template <typename T> 10517141Sgblack@eecs.umich.edu void setBE(T v); 10527141Sgblack@eecs.umich.edu 10537141Sgblack@eecs.umich.edu /** Set the value in the data pointer to v as little endian. */ 10547141Sgblack@eecs.umich.edu template <typename T> 10557141Sgblack@eecs.umich.edu void setLE(T v); 10567141Sgblack@eecs.umich.edu 10577141Sgblack@eecs.umich.edu /** 10587141Sgblack@eecs.umich.edu * Set the value in the data pointer to v using the specified 10597141Sgblack@eecs.umich.edu * endianness. 10607141Sgblack@eecs.umich.edu */ 10617185Sgblack@eecs.umich.edu template <typename T> 10627141Sgblack@eecs.umich.edu void set(T v, ByteOrder endian); 10637141Sgblack@eecs.umich.edu 10647141Sgblack@eecs.umich.edu /** Set the value in the data pointer to v as guest endian. */ 10657141Sgblack@eecs.umich.edu template <typename T> 10667141Sgblack@eecs.umich.edu void set(T v); 10677141Sgblack@eecs.umich.edu 10687141Sgblack@eecs.umich.edu /** 10697141Sgblack@eecs.umich.edu * Copy data into the packet from the provided pointer. 10707141Sgblack@eecs.umich.edu */ 10717146Sgblack@eecs.umich.edu void 10727141Sgblack@eecs.umich.edu setData(const uint8_t *p) 10737141Sgblack@eecs.umich.edu { 10747141Sgblack@eecs.umich.edu // we should never be copying data onto itself, which means we 10757141Sgblack@eecs.umich.edu // must idenfity packets with static data, as they carry the 10767418Sgblack@eecs.umich.edu // same pointer from source to destination and back 10777418Sgblack@eecs.umich.edu assert(p != getPtr<uint8_t>() || flags.isSet(STATIC_DATA)); 10787418Sgblack@eecs.umich.edu 10797418Sgblack@eecs.umich.edu if (p != getPtr<uint8_t>()) 10807418Sgblack@eecs.umich.edu // for packet with allocated dynamic data, we copy data from 10817418Sgblack@eecs.umich.edu // one to the other, e.g. a forwarded response to a response 10827418Sgblack@eecs.umich.edu std::memcpy(getPtr<uint8_t>(), p, getSize()); 10837418Sgblack@eecs.umich.edu } 10847418Sgblack@eecs.umich.edu 10857418Sgblack@eecs.umich.edu /** 10867418Sgblack@eecs.umich.edu * Copy data into the packet from the provided block pointer, 10877418Sgblack@eecs.umich.edu * which is aligned to the given block size. 10887418Sgblack@eecs.umich.edu */ 10897418Sgblack@eecs.umich.edu void 10907418Sgblack@eecs.umich.edu setDataFromBlock(const uint8_t *blk_data, int blkSize) 10917418Sgblack@eecs.umich.edu { 10927418Sgblack@eecs.umich.edu setData(blk_data + getOffset(blkSize)); 10937418Sgblack@eecs.umich.edu } 10947418Sgblack@eecs.umich.edu 10957418Sgblack@eecs.umich.edu /** 10967418Sgblack@eecs.umich.edu * Copy data from the packet to the provided block pointer, which 10977418Sgblack@eecs.umich.edu * is aligned to the given block size. 10987418Sgblack@eecs.umich.edu */ 10997418Sgblack@eecs.umich.edu void 11007418Sgblack@eecs.umich.edu writeData(uint8_t *p) const 11017418Sgblack@eecs.umich.edu { 11027418Sgblack@eecs.umich.edu std::memcpy(p, getConstPtr<uint8_t>(), getSize()); 11037418Sgblack@eecs.umich.edu } 11047418Sgblack@eecs.umich.edu 11057418Sgblack@eecs.umich.edu /** 11067418Sgblack@eecs.umich.edu * Copy data from the packet to the memory at the provided pointer. 11077418Sgblack@eecs.umich.edu */ 11087418Sgblack@eecs.umich.edu void 11097418Sgblack@eecs.umich.edu writeDataToBlock(uint8_t *blk_data, int blkSize) const 11107418Sgblack@eecs.umich.edu { 11117418Sgblack@eecs.umich.edu writeData(blk_data + getOffset(blkSize)); 11127418Sgblack@eecs.umich.edu } 11137418Sgblack@eecs.umich.edu 11147418Sgblack@eecs.umich.edu /** 11157418Sgblack@eecs.umich.edu * delete the data pointed to in the data pointer. Ok to call to 11167418Sgblack@eecs.umich.edu * matter how data was allocted. 11177418Sgblack@eecs.umich.edu */ 11187418Sgblack@eecs.umich.edu void 11197418Sgblack@eecs.umich.edu deleteData() 11207418Sgblack@eecs.umich.edu { 11217418Sgblack@eecs.umich.edu if (flags.isSet(DYNAMIC_DATA)) 11227418Sgblack@eecs.umich.edu delete [] data; 11237418Sgblack@eecs.umich.edu 11247418Sgblack@eecs.umich.edu flags.clear(STATIC_DATA|DYNAMIC_DATA); 11257418Sgblack@eecs.umich.edu data = NULL; 11267141Sgblack@eecs.umich.edu } 11277141Sgblack@eecs.umich.edu 11287141Sgblack@eecs.umich.edu /** Allocate memory for the packet. */ 11297141Sgblack@eecs.umich.edu void 11307141Sgblack@eecs.umich.edu allocate() 11317141Sgblack@eecs.umich.edu { 11327146Sgblack@eecs.umich.edu // if either this command or the response command has a data 11337141Sgblack@eecs.umich.edu // payload, actually allocate space 11347141Sgblack@eecs.umich.edu if (hasData() || hasRespData()) { 11357146Sgblack@eecs.umich.edu assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA)); 11367141Sgblack@eecs.umich.edu flags.set(DYNAMIC_DATA); 11377141Sgblack@eecs.umich.edu data = new uint8_t[getSize()]; 11387141Sgblack@eecs.umich.edu } 11397235Sgblack@eecs.umich.edu } 11407235Sgblack@eecs.umich.edu 11417235Sgblack@eecs.umich.edu /** @} */ 11427235Sgblack@eecs.umich.edu 11437235Sgblack@eecs.umich.edu private: // Private data accessor methods 11447235Sgblack@eecs.umich.edu /** Get the data in the packet without byte swapping. */ 11457235Sgblack@eecs.umich.edu template <typename T> 11467235Sgblack@eecs.umich.edu T getRaw() const; 11477235Sgblack@eecs.umich.edu 11487235Sgblack@eecs.umich.edu /** Set the value in the data pointer to v without byte swapping. */ 11497235Sgblack@eecs.umich.edu template <typename T> 11507235Sgblack@eecs.umich.edu void setRaw(T v); 11517235Sgblack@eecs.umich.edu 11527235Sgblack@eecs.umich.edu public: 11537235Sgblack@eecs.umich.edu /** 11547141Sgblack@eecs.umich.edu * Check a functional request against a memory value stored in 11557432Sgblack@eecs.umich.edu * another packet (i.e. an in-transit request or 11567141Sgblack@eecs.umich.edu * response). Returns true if the current packet is a read, and 11577154Sgblack@eecs.umich.edu * the other packet provides the data, which is then copied to the 11587154Sgblack@eecs.umich.edu * current packet. If the current packet is a write, and the other 11597154Sgblack@eecs.umich.edu * packet intersects this one, then we update the data 11607154Sgblack@eecs.umich.edu * accordingly. 11617141Sgblack@eecs.umich.edu */ 11627141Sgblack@eecs.umich.edu bool 11637201Sgblack@eecs.umich.edu checkFunctional(PacketPtr other) 11647201Sgblack@eecs.umich.edu { 11657201Sgblack@eecs.umich.edu // all packets that are carrying a payload should have a valid 11667201Sgblack@eecs.umich.edu // data pointer 11677201Sgblack@eecs.umich.edu return checkFunctional(other, other->getAddr(), other->isSecure(), 11687201Sgblack@eecs.umich.edu other->getSize(), 11697141Sgblack@eecs.umich.edu other->hasData() ? 11707141Sgblack@eecs.umich.edu other->getPtr<uint8_t>() : NULL); 11717141Sgblack@eecs.umich.edu } 11727141Sgblack@eecs.umich.edu 11737308Sgblack@eecs.umich.edu /** 11747141Sgblack@eecs.umich.edu * Does the request need to check for cached copies of the same block 11757316Sgblack@eecs.umich.edu * in the memory hierarchy above. 11767316Sgblack@eecs.umich.edu **/ 11777316Sgblack@eecs.umich.edu bool 11787316Sgblack@eecs.umich.edu mustCheckAbove() const 11797141Sgblack@eecs.umich.edu { 11807141Sgblack@eecs.umich.edu return cmd == MemCmd::HardPFReq || isEviction(); 11817141Sgblack@eecs.umich.edu } 11827212Sgblack@eecs.umich.edu 11837212Sgblack@eecs.umich.edu /** 11847212Sgblack@eecs.umich.edu * Is this packet a clean eviction, including both actual clean 11857212Sgblack@eecs.umich.edu * evict packets, but also clean writebacks. 11867212Sgblack@eecs.umich.edu */ 11877212Sgblack@eecs.umich.edu bool 11887212Sgblack@eecs.umich.edu isCleanEviction() const 11897212Sgblack@eecs.umich.edu { 11907212Sgblack@eecs.umich.edu return cmd == MemCmd::CleanEvict || cmd == MemCmd::WritebackClean; 11917212Sgblack@eecs.umich.edu } 11927212Sgblack@eecs.umich.edu 11937212Sgblack@eecs.umich.edu /** 11947212Sgblack@eecs.umich.edu * Check a functional request against a memory value represented 11957141Sgblack@eecs.umich.edu * by a base/size pair and an associated data array. If the 11967141Sgblack@eecs.umich.edu * current packet is a read, it may be satisfied by the memory 11977432Sgblack@eecs.umich.edu * value. If the current packet is a write, it may update the 11987141Sgblack@eecs.umich.edu * memory value. 11997154Sgblack@eecs.umich.edu */ 12007154Sgblack@eecs.umich.edu bool 12017154Sgblack@eecs.umich.edu checkFunctional(Printable *obj, Addr base, bool is_secure, int size, 12027154Sgblack@eecs.umich.edu uint8_t *_data); 12037141Sgblack@eecs.umich.edu 12047141Sgblack@eecs.umich.edu /** 12057201Sgblack@eecs.umich.edu * Push label for PrintReq (safe to call unconditionally). 12067201Sgblack@eecs.umich.edu */ 12077201Sgblack@eecs.umich.edu void 12087201Sgblack@eecs.umich.edu pushLabel(const std::string &lbl) 12097201Sgblack@eecs.umich.edu { 12107201Sgblack@eecs.umich.edu if (isPrint()) 12117141Sgblack@eecs.umich.edu safe_cast<PrintReqState*>(senderState)->pushLabel(lbl); 12127410Sgblack@eecs.umich.edu } 12137141Sgblack@eecs.umich.edu 12147141Sgblack@eecs.umich.edu /** 12157408Sgblack@eecs.umich.edu * Pop label for PrintReq (safe to call unconditionally). 12167141Sgblack@eecs.umich.edu */ 12177141Sgblack@eecs.umich.edu void 12187248Sgblack@eecs.umich.edu popLabel() 12197141Sgblack@eecs.umich.edu { 12207419Sgblack@eecs.umich.edu if (isPrint()) 12217141Sgblack@eecs.umich.edu safe_cast<PrintReqState*>(senderState)->popLabel(); 12227419Sgblack@eecs.umich.edu } 12237141Sgblack@eecs.umich.edu 12247419Sgblack@eecs.umich.edu void print(std::ostream &o, int verbosity = 0, 12257141Sgblack@eecs.umich.edu const std::string &prefix = "") const; 12267419Sgblack@eecs.umich.edu 12277141Sgblack@eecs.umich.edu /** 12287141Sgblack@eecs.umich.edu * A no-args wrapper of print(std::ostream...) 12297141Sgblack@eecs.umich.edu * meant to be invoked from DPRINTFs 12307141Sgblack@eecs.umich.edu * avoiding string overheads in fast mode 12317141Sgblack@eecs.umich.edu * @return string with the request's type and start<->end addresses 12327141Sgblack@eecs.umich.edu */ 12337141Sgblack@eecs.umich.edu std::string print() const; 12347141Sgblack@eecs.umich.edu}; 12357141Sgblack@eecs.umich.edu 12367141Sgblack@eecs.umich.edu#endif //__MEM_PACKET_HH 12377141Sgblack@eecs.umich.edu