packet.hh revision 8949:3fa1ee293096
15217Ssaidi@eecs.umich.edu/* 213610Sgiacomo.gabrielli@arm.com * Copyright (c) 2012 ARM Limited 39920Syasuko.eckert@amd.com * All rights reserved 49428SAndreas.Sandberg@ARM.com * 59428SAndreas.Sandberg@ARM.com * The license below extends only to copyright in the software and shall 69428SAndreas.Sandberg@ARM.com * not be construed as granting a license to any other intellectual 79428SAndreas.Sandberg@ARM.com * property including but not limited to intellectual property relating 89428SAndreas.Sandberg@ARM.com * to a hardware implementation of the functionality of the software 99428SAndreas.Sandberg@ARM.com * licensed hereunder. You may use the software subject to the license 109428SAndreas.Sandberg@ARM.com * terms below provided that you ensure that this notice is replicated 119428SAndreas.Sandberg@ARM.com * unmodified and in its entirety in all distributions of the software, 129428SAndreas.Sandberg@ARM.com * modified or unmodified, in source code or in binary form. 139428SAndreas.Sandberg@ARM.com * 149428SAndreas.Sandberg@ARM.com * Copyright (c) 2006 The Regents of The University of Michigan 155217Ssaidi@eecs.umich.edu * Copyright (c) 2010 Advanced Micro Devices, Inc. 165217Ssaidi@eecs.umich.edu * All rights reserved. 175217Ssaidi@eecs.umich.edu * 185217Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 195217Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are 205217Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright 215217Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 225217Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 235217Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 245217Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution; 255217Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its 265217Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from 275217Ssaidi@eecs.umich.edu * this software without specific prior written permission. 285217Ssaidi@eecs.umich.edu * 295217Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 305217Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 315217Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 325217Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 335217Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 345217Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 355217Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 365217Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 375217Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 385217Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 395217Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 405217Ssaidi@eecs.umich.edu * 415217Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski 425217Ssaidi@eecs.umich.edu * Steve Reinhardt 435217Ssaidi@eecs.umich.edu * Ali Saidi 4411793Sbrandon.potter@amd.com */ 4511793Sbrandon.potter@amd.com 4613610Sgiacomo.gabrielli@arm.com/** 4711627Smichael.lebeane@amd.com * @file 4812334Sgabeblack@google.com * Declaration of the Packet class. 495217Ssaidi@eecs.umich.edu */ 506658Snate@binkert.org 519441SAndreas.Sandberg@ARM.com#ifndef __MEM_PACKET_HH__ 529441SAndreas.Sandberg@ARM.com#define __MEM_PACKET_HH__ 538232Snate@binkert.org 5411627Smichael.lebeane@amd.com#include <bitset> 5511627Smichael.lebeane@amd.com#include <cassert> 569441SAndreas.Sandberg@ARM.com#include <list> 575217Ssaidi@eecs.umich.edu 585217Ssaidi@eecs.umich.edu#include "base/cast.hh" 595217Ssaidi@eecs.umich.edu#include "base/compiler.hh" 605217Ssaidi@eecs.umich.edu#include "base/fast_alloc.hh" 615217Ssaidi@eecs.umich.edu#include "base/flags.hh" 625217Ssaidi@eecs.umich.edu#include "base/misc.hh" 635217Ssaidi@eecs.umich.edu#include "base/printable.hh" 645217Ssaidi@eecs.umich.edu#include "base/types.hh" 6513557Sgabeblack@google.com#include "mem/request.hh" 6613557Sgabeblack@google.com#include "sim/core.hh" 675217Ssaidi@eecs.umich.edu 685217Ssaidi@eecs.umich.educlass Packet; 695217Ssaidi@eecs.umich.edutypedef Packet *PacketPtr; 705217Ssaidi@eecs.umich.edutypedef uint8_t* PacketDataPtr; 715217Ssaidi@eecs.umich.edutypedef std::list<PacketPtr> PacketList; 725217Ssaidi@eecs.umich.edu 735217Ssaidi@eecs.umich.educlass MemCmd 7413611Sgabeblack@google.com{ 7513611Sgabeblack@google.com friend class Packet; 765217Ssaidi@eecs.umich.edu 775217Ssaidi@eecs.umich.edu public: 785217Ssaidi@eecs.umich.edu /** 795217Ssaidi@eecs.umich.edu * List of all commands associated with a packet. 8012109SRekai.GonzalezAlberquilla@arm.com */ 8112109SRekai.GonzalezAlberquilla@arm.com enum Command 8212109SRekai.GonzalezAlberquilla@arm.com { 8312109SRekai.GonzalezAlberquilla@arm.com InvalidCmd, 8412109SRekai.GonzalezAlberquilla@arm.com ReadReq, 8512109SRekai.GonzalezAlberquilla@arm.com ReadResp, 8612109SRekai.GonzalezAlberquilla@arm.com ReadRespWithInvalidate, 8712109SRekai.GonzalezAlberquilla@arm.com WriteReq, 8812109SRekai.GonzalezAlberquilla@arm.com WriteResp, 8912109SRekai.GonzalezAlberquilla@arm.com Writeback, 9013610Sgiacomo.gabrielli@arm.com SoftPFReq, 9113610Sgiacomo.gabrielli@arm.com HardPFReq, 9213610Sgiacomo.gabrielli@arm.com SoftPFResp, 9313610Sgiacomo.gabrielli@arm.com HardPFResp, 9413610Sgiacomo.gabrielli@arm.com WriteInvalidateReq, 9513610Sgiacomo.gabrielli@arm.com WriteInvalidateResp, 9613610Sgiacomo.gabrielli@arm.com UpgradeReq, 9713610Sgiacomo.gabrielli@arm.com SCUpgradeReq, // Special "weak" upgrade for StoreCond 9813610Sgiacomo.gabrielli@arm.com UpgradeResp, 9913610Sgiacomo.gabrielli@arm.com SCUpgradeFailReq, // Failed SCUpgradeReq in MSHR (never sent) 10013610Sgiacomo.gabrielli@arm.com UpgradeFailResp, // Valid for SCUpgradeReq only 1015217Ssaidi@eecs.umich.edu ReadExReq, 10213557Sgabeblack@google.com ReadExResp, 10313557Sgabeblack@google.com LoadLockedReq, 1045217Ssaidi@eecs.umich.edu StoreCondReq, 1055217Ssaidi@eecs.umich.edu StoreCondFailReq, // Failed StoreCondReq in MSHR (never sent) 1065217Ssaidi@eecs.umich.edu StoreCondResp, 1075217Ssaidi@eecs.umich.edu SwapReq, 1085217Ssaidi@eecs.umich.edu SwapResp, 1099920Syasuko.eckert@amd.com MessageReq, 1109920Syasuko.eckert@amd.com MessageResp, 1119920Syasuko.eckert@amd.com // Error responses 1129920Syasuko.eckert@amd.com // @TODO these should be classified as responses rather than 1139920Syasuko.eckert@amd.com // requests; coding them as requests initially for backwards 1149920Syasuko.eckert@amd.com // compatibility 1159920Syasuko.eckert@amd.com NetworkNackError, // nacked at network layer (not by protocol) 1169920Syasuko.eckert@amd.com InvalidDestError, // packet dest field invalid 1177720Sgblack@eecs.umich.edu BadAddressError, // memory address invalid 1187720Sgblack@eecs.umich.edu FunctionalReadError, // unable to fulfill functional read 1195712Shsul@eecs.umich.edu FunctionalWriteError, // unable to fulfill functional write 1205712Shsul@eecs.umich.edu // Fake simulator-only commands 1215217Ssaidi@eecs.umich.edu PrintReq, // Print state matching address 1225217Ssaidi@eecs.umich.edu FlushReq, //request for a cache flush 1235714Shsul@eecs.umich.edu InvalidationReq, // request for address to be invalidated from lsq 12411005Sandreas.sandberg@arm.com NUM_MEM_CMDS 12511005Sandreas.sandberg@arm.com }; 12611005Sandreas.sandberg@arm.com 1275714Shsul@eecs.umich.edu private: 1285714Shsul@eecs.umich.edu /** 1295714Shsul@eecs.umich.edu * List of command attributes. 1305217Ssaidi@eecs.umich.edu */ 1319428SAndreas.Sandberg@ARM.com enum Attribute 1329428SAndreas.Sandberg@ARM.com { 13311627Smichael.lebeane@amd.com IsRead, //!< Data flows from responder to requester 13411627Smichael.lebeane@amd.com IsWrite, //!< Data flows from requester to responder 13511627Smichael.lebeane@amd.com IsUpgrade, 13611627Smichael.lebeane@amd.com IsPrefetch, //!< Not a demand access 13711627Smichael.lebeane@amd.com IsInvalidate, 13811627Smichael.lebeane@amd.com NeedsExclusive, //!< Requires exclusive copy to complete in-cache 13911627Smichael.lebeane@amd.com IsRequest, //!< Issued by requester 14011627Smichael.lebeane@amd.com IsResponse, //!< Issue by responder 14111627Smichael.lebeane@amd.com NeedsResponse, //!< Requester needs response from target 14211627Smichael.lebeane@amd.com IsSWPrefetch, 14311627Smichael.lebeane@amd.com IsHWPrefetch, 14411627Smichael.lebeane@amd.com IsLlsc, //!< Alpha/MIPS LL or SC access 14511627Smichael.lebeane@amd.com HasData, //!< There is an associated payload 14611627Smichael.lebeane@amd.com IsError, //!< Error response 14711627Smichael.lebeane@amd.com IsPrint, //!< Print state matching address (for debugging) 14811627Smichael.lebeane@amd.com IsFlush, //!< Flush the address from caches 14911627Smichael.lebeane@amd.com NUM_COMMAND_ATTRIBUTES 15011627Smichael.lebeane@amd.com }; 15111627Smichael.lebeane@amd.com 15211627Smichael.lebeane@amd.com /** 15311627Smichael.lebeane@amd.com * Structure that defines attributes and other data associated 15411627Smichael.lebeane@amd.com * with a Command. 15511627Smichael.lebeane@amd.com */ 15611627Smichael.lebeane@amd.com struct CommandInfo 15711627Smichael.lebeane@amd.com { 15811627Smichael.lebeane@amd.com /// Set of attribute flags. 15911627Smichael.lebeane@amd.com const std::bitset<NUM_COMMAND_ATTRIBUTES> attributes; 16011627Smichael.lebeane@amd.com /// Corresponding response for requests; InvalidCmd if no 16111627Smichael.lebeane@amd.com /// response is applicable. 16211627Smichael.lebeane@amd.com const Command response; 16311627Smichael.lebeane@amd.com /// String representation (for printing) 16411627Smichael.lebeane@amd.com const std::string str; 16511627Smichael.lebeane@amd.com }; 16610905Sandreas.sandberg@arm.com 1679428SAndreas.Sandberg@ARM.com /// Array to map Command enum to associated info. 1689428SAndreas.Sandberg@ARM.com static const CommandInfo commandInfo[]; 1699428SAndreas.Sandberg@ARM.com 17013557Sgabeblack@google.com private: 1719428SAndreas.Sandberg@ARM.com 17213611Sgabeblack@google.com Command cmd; 1739428SAndreas.Sandberg@ARM.com 1749428SAndreas.Sandberg@ARM.com bool 17510905Sandreas.sandberg@arm.com testCmdAttrib(MemCmd::Attribute attrib) const 1769428SAndreas.Sandberg@ARM.com { 17712109SRekai.GonzalezAlberquilla@arm.com return commandInfo[cmd].attributes[attrib] != 0; 17812109SRekai.GonzalezAlberquilla@arm.com } 17912109SRekai.GonzalezAlberquilla@arm.com 18012109SRekai.GonzalezAlberquilla@arm.com public: 18112109SRekai.GonzalezAlberquilla@arm.com 18212109SRekai.GonzalezAlberquilla@arm.com bool isRead() const { return testCmdAttrib(IsRead); } 18313610Sgiacomo.gabrielli@arm.com bool isWrite() const { return testCmdAttrib(IsWrite); } 18413610Sgiacomo.gabrielli@arm.com bool isUpgrade() const { return testCmdAttrib(IsUpgrade); } 18513610Sgiacomo.gabrielli@arm.com bool isRequest() const { return testCmdAttrib(IsRequest); } 18613610Sgiacomo.gabrielli@arm.com bool isResponse() const { return testCmdAttrib(IsResponse); } 18713610Sgiacomo.gabrielli@arm.com bool needsExclusive() const { return testCmdAttrib(NeedsExclusive); } 18813610Sgiacomo.gabrielli@arm.com bool needsResponse() const { return testCmdAttrib(NeedsResponse); } 18913557Sgabeblack@google.com bool isInvalidate() const { return testCmdAttrib(IsInvalidate); } 1909428SAndreas.Sandberg@ARM.com bool hasData() const { return testCmdAttrib(HasData); } 1919428SAndreas.Sandberg@ARM.com bool isReadWrite() const { return isRead() && isWrite(); } 1929428SAndreas.Sandberg@ARM.com bool isLLSC() const { return testCmdAttrib(IsLlsc); } 1939428SAndreas.Sandberg@ARM.com bool isError() const { return testCmdAttrib(IsError); } 1949920Syasuko.eckert@amd.com bool isPrint() const { return testCmdAttrib(IsPrint); } 1959920Syasuko.eckert@amd.com bool isFlush() const { return testCmdAttrib(IsFlush); } 1969920Syasuko.eckert@amd.com 1979920Syasuko.eckert@amd.com const Command 1989920Syasuko.eckert@amd.com responseCommand() const 1999920Syasuko.eckert@amd.com { 2009920Syasuko.eckert@amd.com return commandInfo[cmd].response; 20110905Sandreas.sandberg@arm.com } 2029428SAndreas.Sandberg@ARM.com 2039428SAndreas.Sandberg@ARM.com /// Return the string to a cmd given by idx. 2049428SAndreas.Sandberg@ARM.com const std::string &toString() const { return commandInfo[cmd].str; } 2059428SAndreas.Sandberg@ARM.com int toInt() const { return (int)cmd; } 2069428SAndreas.Sandberg@ARM.com 20710905Sandreas.sandberg@arm.com MemCmd(Command _cmd) : cmd(_cmd) { } 2089428SAndreas.Sandberg@ARM.com MemCmd(int _cmd) : cmd((Command)_cmd) { } 2099428SAndreas.Sandberg@ARM.com MemCmd() : cmd(InvalidCmd) { } 2109428SAndreas.Sandberg@ARM.com 21113557Sgabeblack@google.com bool operator==(MemCmd c2) const { return (cmd == c2.cmd); } 2129428SAndreas.Sandberg@ARM.com bool operator!=(MemCmd c2) const { return (cmd != c2.cmd); } 2139428SAndreas.Sandberg@ARM.com}; 21410905Sandreas.sandberg@arm.com 2159428SAndreas.Sandberg@ARM.com/** 21613611Sgabeblack@google.com * A Packet is used to encapsulate a transfer between two objects in 2179428SAndreas.Sandberg@ARM.com * the memory system (e.g., the L1 and L2 cache). (In contrast, a 21812109SRekai.GonzalezAlberquilla@arm.com * single Request travels all the way from the requester to the 21912109SRekai.GonzalezAlberquilla@arm.com * ultimate destination and back, possibly being conveyed by several 22012109SRekai.GonzalezAlberquilla@arm.com * different Packets along the way.) 22112109SRekai.GonzalezAlberquilla@arm.com */ 22212109SRekai.GonzalezAlberquilla@arm.comclass Packet : public FastAlloc, public Printable 22312109SRekai.GonzalezAlberquilla@arm.com{ 22413610Sgiacomo.gabrielli@arm.com public: 22513610Sgiacomo.gabrielli@arm.com typedef uint32_t FlagsType; 22613610Sgiacomo.gabrielli@arm.com typedef ::Flags<FlagsType> Flags; 22713610Sgiacomo.gabrielli@arm.com typedef short NodeID; 22813610Sgiacomo.gabrielli@arm.com 22913610Sgiacomo.gabrielli@arm.com private: 23013557Sgabeblack@google.com static const FlagsType PUBLIC_FLAGS = 0x00000000; 2319428SAndreas.Sandberg@ARM.com static const FlagsType PRIVATE_FLAGS = 0x00007F0F; 2329428SAndreas.Sandberg@ARM.com static const FlagsType COPY_FLAGS = 0x0000000F; 2339428SAndreas.Sandberg@ARM.com 2349428SAndreas.Sandberg@ARM.com static const FlagsType SHARED = 0x00000001; 2359920Syasuko.eckert@amd.com // Special control flags 2369920Syasuko.eckert@amd.com /// Special timing-mode atomic snoop for multi-level coherence. 2379920Syasuko.eckert@amd.com static const FlagsType EXPRESS_SNOOP = 0x00000002; 2389920Syasuko.eckert@amd.com /// Does supplier have exclusive copy? 2399920Syasuko.eckert@amd.com /// Useful for multi-level coherence. 2409920Syasuko.eckert@amd.com static const FlagsType SUPPLY_EXCLUSIVE = 0x00000004; 2419920Syasuko.eckert@amd.com // Snoop response flags 2429428SAndreas.Sandberg@ARM.com static const FlagsType MEM_INHIBIT = 0x00000008; 24310905Sandreas.sandberg@arm.com /// Are the 'addr' and 'size' fields valid? 2449428SAndreas.Sandberg@ARM.com static const FlagsType VALID_ADDR = 0x00000100; 2459428SAndreas.Sandberg@ARM.com static const FlagsType VALID_SIZE = 0x00000200; 2469428SAndreas.Sandberg@ARM.com /// Is the 'src' field valid? 2479428SAndreas.Sandberg@ARM.com static const FlagsType VALID_SRC = 0x00000400; 2489441SAndreas.Sandberg@ARM.com static const FlagsType VALID_DST = 0x00000800; 2499441SAndreas.Sandberg@ARM.com /// Is the data pointer set to a value that shouldn't be freed 2509441SAndreas.Sandberg@ARM.com /// when the packet is destroyed? 2519441SAndreas.Sandberg@ARM.com static const FlagsType STATIC_DATA = 0x00001000; 2529441SAndreas.Sandberg@ARM.com /// The data pointer points to a value that should be freed when 2539441SAndreas.Sandberg@ARM.com /// the packet is destroyed. 2549441SAndreas.Sandberg@ARM.com static const FlagsType DYNAMIC_DATA = 0x00002000; 2559441SAndreas.Sandberg@ARM.com /// the data pointer points to an array (thus delete []) needs to 2569441SAndreas.Sandberg@ARM.com /// be called on it rather than simply delete. 2579441SAndreas.Sandberg@ARM.com static const FlagsType ARRAY_DATA = 0x00004000; 2589441SAndreas.Sandberg@ARM.com /// suppress the error if this packet encounters a functional 2599441SAndreas.Sandberg@ARM.com /// access failure. 2609441SAndreas.Sandberg@ARM.com static const FlagsType SUPPRESS_FUNC_ERROR = 0x00008000; 2619441SAndreas.Sandberg@ARM.com 2629441SAndreas.Sandberg@ARM.com Flags flags; 2639441SAndreas.Sandberg@ARM.com 2649441SAndreas.Sandberg@ARM.com public: 2659441SAndreas.Sandberg@ARM.com typedef MemCmd::Command Command; 2669441SAndreas.Sandberg@ARM.com 2679441SAndreas.Sandberg@ARM.com /// The command field of the packet. 2689441SAndreas.Sandberg@ARM.com MemCmd cmd; 2699441SAndreas.Sandberg@ARM.com 2709441SAndreas.Sandberg@ARM.com /// A pointer to the original request. 2719441SAndreas.Sandberg@ARM.com RequestPtr req; 2729441SAndreas.Sandberg@ARM.com 2739441SAndreas.Sandberg@ARM.com private: 2749441SAndreas.Sandberg@ARM.com /** 2759441SAndreas.Sandberg@ARM.com * A pointer to the data being transfered. It can be differnt 2769441SAndreas.Sandberg@ARM.com * sizes at each level of the heirarchy so it belongs in the 2779441SAndreas.Sandberg@ARM.com * packet, not request. This may or may not be populated when a 2789441SAndreas.Sandberg@ARM.com * responder recieves the packet. If not populated it memory should 2799441SAndreas.Sandberg@ARM.com * be allocated. 2809441SAndreas.Sandberg@ARM.com */ 2819441SAndreas.Sandberg@ARM.com PacketDataPtr data; 282 283 /// The address of the request. This address could be virtual or 284 /// physical, depending on the system configuration. 285 Addr addr; 286 287 /// The size of the request or transfer. 288 unsigned size; 289 290 /** 291 * Device address (e.g., bus ID) of the source of the 292 * transaction. The source is not responsible for setting this 293 * field; it is set implicitly by the interconnect when the packet 294 * is first sent. 295 */ 296 NodeID src; 297 298 /** 299 * Device address (e.g., bus ID) of the destination of the 300 * transaction. The special value Broadcast indicates that the 301 * packet should be routed based on its address. This field is 302 * initialized in the constructor and is thus always valid (unlike 303 * addr, size, and src). 304 */ 305 NodeID dest; 306 307 /** 308 * The original value of the command field. Only valid when the 309 * current command field is an error condition; in that case, the 310 * previous contents of the command field are copied here. This 311 * field is *not* set on non-error responses. 312 */ 313 MemCmd origCmd; 314 315 /** 316 * These values specify the range of bytes found that satisfy a 317 * functional read. 318 */ 319 uint16_t bytesValidStart; 320 uint16_t bytesValidEnd; 321 322 public: 323 /// Used to calculate latencies for each packet. 324 Tick time; 325 326 /// The time at which the packet will be fully transmitted 327 Tick finishTime; 328 329 /// The time at which the first chunk of the packet will be transmitted 330 Tick firstWordTime; 331 332 /** 333 * A virtual base opaque structure used to hold state associated 334 * with the packet but specific to the sending device (e.g., an 335 * MSHR). A pointer to this state is returned in the packet's 336 * response so that the sender can quickly look up the state 337 * needed to process it. A specific subclass would be derived 338 * from this to carry state specific to a particular sending 339 * device. 340 */ 341 struct SenderState 342 { 343 virtual ~SenderState() {} 344 }; 345 346 /** 347 * Object used to maintain state of a PrintReq. The senderState 348 * field of a PrintReq should always be of this type. 349 */ 350 class PrintReqState : public SenderState, public FastAlloc 351 { 352 private: 353 /** 354 * An entry in the label stack. 355 */ 356 struct LabelStackEntry 357 { 358 const std::string label; 359 std::string *prefix; 360 bool labelPrinted; 361 LabelStackEntry(const std::string &_label, std::string *_prefix); 362 }; 363 364 typedef std::list<LabelStackEntry> LabelStack; 365 LabelStack labelStack; 366 367 std::string *curPrefixPtr; 368 369 public: 370 std::ostream &os; 371 const int verbosity; 372 373 PrintReqState(std::ostream &os, int verbosity = 0); 374 ~PrintReqState(); 375 376 /** 377 * Returns the current line prefix. 378 */ 379 const std::string &curPrefix() { return *curPrefixPtr; } 380 381 /** 382 * Push a label onto the label stack, and prepend the given 383 * prefix string onto the current prefix. Labels will only be 384 * printed if an object within the label's scope is printed. 385 */ 386 void pushLabel(const std::string &lbl, 387 const std::string &prefix = " "); 388 389 /** 390 * Pop a label off the label stack. 391 */ 392 void popLabel(); 393 394 /** 395 * Print all of the pending unprinted labels on the 396 * stack. Called by printObj(), so normally not called by 397 * users unless bypassing printObj(). 398 */ 399 void printLabels(); 400 401 /** 402 * Print a Printable object to os, because it matched the 403 * address on a PrintReq. 404 */ 405 void printObj(Printable *obj); 406 }; 407 408 /** 409 * This packet's sender state. Devices should use dynamic_cast<> 410 * to cast to the state appropriate to the sender. The intent of 411 * this variable is to allow a device to attach extra information 412 * to a request. A response packet must return the sender state 413 * that was attached to the original request (even if a new packet 414 * is created). 415 */ 416 SenderState *senderState; 417 418 /// Return the string name of the cmd field (for debugging and 419 /// tracing). 420 const std::string &cmdString() const { return cmd.toString(); } 421 422 /// Return the index of this command. 423 inline int cmdToIndex() const { return cmd.toInt(); } 424 425 bool isRead() const { return cmd.isRead(); } 426 bool isWrite() const { return cmd.isWrite(); } 427 bool isUpgrade() const { return cmd.isUpgrade(); } 428 bool isRequest() const { return cmd.isRequest(); } 429 bool isResponse() const { return cmd.isResponse(); } 430 bool needsExclusive() const { return cmd.needsExclusive(); } 431 bool needsResponse() const { return cmd.needsResponse(); } 432 bool isInvalidate() const { return cmd.isInvalidate(); } 433 bool hasData() const { return cmd.hasData(); } 434 bool isReadWrite() const { return cmd.isReadWrite(); } 435 bool isLLSC() const { return cmd.isLLSC(); } 436 bool isError() const { return cmd.isError(); } 437 bool isPrint() const { return cmd.isPrint(); } 438 bool isFlush() const { return cmd.isFlush(); } 439 440 // Snoop flags 441 void assertMemInhibit() { flags.set(MEM_INHIBIT); } 442 bool memInhibitAsserted() { return flags.isSet(MEM_INHIBIT); } 443 void assertShared() { flags.set(SHARED); } 444 bool sharedAsserted() { return flags.isSet(SHARED); } 445 446 // Special control flags 447 void setExpressSnoop() { flags.set(EXPRESS_SNOOP); } 448 bool isExpressSnoop() { return flags.isSet(EXPRESS_SNOOP); } 449 void setSupplyExclusive() { flags.set(SUPPLY_EXCLUSIVE); } 450 void clearSupplyExclusive() { flags.clear(SUPPLY_EXCLUSIVE); } 451 bool isSupplyExclusive() { return flags.isSet(SUPPLY_EXCLUSIVE); } 452 void setSuppressFuncError() { flags.set(SUPPRESS_FUNC_ERROR); } 453 bool suppressFuncError() { return flags.isSet(SUPPRESS_FUNC_ERROR); } 454 455 // Network error conditions... encapsulate them as methods since 456 // their encoding keeps changing (from result field to command 457 // field, etc.) 458 void 459 setNacked() 460 { 461 assert(isResponse()); 462 cmd = MemCmd::NetworkNackError; 463 } 464 465 void 466 setBadAddress() 467 { 468 assert(isResponse()); 469 cmd = MemCmd::BadAddressError; 470 } 471 472 bool wasNacked() const { return cmd == MemCmd::NetworkNackError; } 473 bool hadBadAddress() const { return cmd == MemCmd::BadAddressError; } 474 void copyError(Packet *pkt) { assert(pkt->isError()); cmd = pkt->cmd; } 475 476 bool isSrcValid() { return flags.isSet(VALID_SRC); } 477 /// Accessor function to get the source index of the packet. 478 NodeID getSrc() const { assert(flags.isSet(VALID_SRC)); return src; } 479 /// Accessor function to set the source index of the packet. 480 void setSrc(NodeID _src) { src = _src; flags.set(VALID_SRC); } 481 /// Reset source field, e.g. to retransmit packet on different bus. 482 void clearSrc() { flags.clear(VALID_SRC); } 483 484 bool isDestValid() { return flags.isSet(VALID_DST); } 485 /// Accessor function for the destination index of the packet. 486 NodeID getDest() const { assert(flags.isSet(VALID_DST)); return dest; } 487 /// Accessor function to set the destination index of the packet. 488 void setDest(NodeID _dest) { dest = _dest; flags.set(VALID_DST); } 489 /// Reset destination field, e.g. to turn a response into a request again. 490 void clearDest() { flags.clear(VALID_DST); } 491 492 Addr getAddr() const { assert(flags.isSet(VALID_ADDR)); return addr; } 493 unsigned getSize() const { assert(flags.isSet(VALID_SIZE)); return size; } 494 Addr getOffset(int blkSize) const { return getAddr() & (Addr)(blkSize - 1); } 495 496 /** 497 * It has been determined that the SC packet should successfully update 498 * memory. Therefore, convert this SC packet to a normal write. 499 */ 500 void 501 convertScToWrite() 502 { 503 assert(isLLSC()); 504 assert(isWrite()); 505 cmd = MemCmd::WriteReq; 506 } 507 508 /** 509 * When ruby is in use, Ruby will monitor the cache line and thus M5 510 * phys memory should treat LL ops as normal reads. 511 */ 512 void 513 convertLlToRead() 514 { 515 assert(isLLSC()); 516 assert(isRead()); 517 cmd = MemCmd::ReadReq; 518 } 519 520 /** 521 * Constructor. Note that a Request object must be constructed 522 * first, but the Requests's physical address and size fields need 523 * not be valid. The command and destination addresses must be 524 * supplied. 525 */ 526 Packet(Request *_req, MemCmd _cmd) 527 : cmd(_cmd), req(_req), data(NULL), 528 bytesValidStart(0), bytesValidEnd(0), 529 time(curTick()), senderState(NULL) 530 { 531 if (req->hasPaddr()) { 532 addr = req->getPaddr(); 533 flags.set(VALID_ADDR); 534 } 535 if (req->hasSize()) { 536 size = req->getSize(); 537 flags.set(VALID_SIZE); 538 } 539 } 540 541 /** 542 * Alternate constructor if you are trying to create a packet with 543 * a request that is for a whole block, not the address from the 544 * req. this allows for overriding the size/addr of the req. 545 */ 546 Packet(Request *_req, MemCmd _cmd, int _blkSize) 547 : cmd(_cmd), req(_req), data(NULL), 548 bytesValidStart(0), bytesValidEnd(0), 549 time(curTick()), senderState(NULL) 550 { 551 if (req->hasPaddr()) { 552 addr = req->getPaddr() & ~(_blkSize - 1); 553 flags.set(VALID_ADDR); 554 } 555 size = _blkSize; 556 flags.set(VALID_SIZE); 557 } 558 559 /** 560 * Alternate constructor for copying a packet. Copy all fields 561 * *except* if the original packet's data was dynamic, don't copy 562 * that, as we can't guarantee that the new packet's lifetime is 563 * less than that of the original packet. In this case the new 564 * packet should allocate its own data. 565 */ 566 Packet(Packet *pkt, bool clearFlags = false) 567 : cmd(pkt->cmd), req(pkt->req), 568 data(pkt->flags.isSet(STATIC_DATA) ? pkt->data : NULL), 569 addr(pkt->addr), size(pkt->size), src(pkt->src), dest(pkt->dest), 570 bytesValidStart(pkt->bytesValidStart), bytesValidEnd(pkt->bytesValidEnd), 571 time(curTick()), senderState(pkt->senderState) 572 { 573 if (!clearFlags) 574 flags.set(pkt->flags & COPY_FLAGS); 575 576 flags.set(pkt->flags & (VALID_ADDR|VALID_SIZE|VALID_SRC|VALID_DST)); 577 flags.set(pkt->flags & STATIC_DATA); 578 579 } 580 581 /** 582 * clean up packet variables 583 */ 584 ~Packet() 585 { 586 // If this is a request packet for which there's no response, 587 // delete the request object here, since the requester will 588 // never get the chance. 589 if (req && isRequest() && !needsResponse()) 590 delete req; 591 deleteData(); 592 } 593 594 /** 595 * Reinitialize packet address and size from the associated 596 * Request object, and reset other fields that may have been 597 * modified by a previous transaction. Typically called when a 598 * statically allocated Request/Packet pair is reused for multiple 599 * transactions. 600 */ 601 void 602 reinitFromRequest() 603 { 604 assert(req->hasPaddr()); 605 flags = 0; 606 addr = req->getPaddr(); 607 size = req->getSize(); 608 time = req->time(); 609 610 flags.set(VALID_ADDR|VALID_SIZE); 611 deleteData(); 612 } 613 614 /** 615 * Take a request packet and modify it in place to be suitable for 616 * returning as a response to that request. The source and 617 * destination fields are *not* modified, as is appropriate for 618 * atomic accesses. 619 */ 620 void 621 makeResponse() 622 { 623 assert(needsResponse()); 624 assert(isRequest()); 625 origCmd = cmd; 626 cmd = cmd.responseCommand(); 627 628 // responses are never express, even if the snoop that 629 // triggered them was 630 flags.clear(EXPRESS_SNOOP); 631 632 dest = src; 633 flags.set(VALID_DST, flags.isSet(VALID_SRC)); 634 flags.clear(VALID_SRC); 635 } 636 637 void 638 makeAtomicResponse() 639 { 640 makeResponse(); 641 } 642 643 void 644 makeTimingResponse() 645 { 646 makeResponse(); 647 } 648 649 void 650 setFunctionalResponseStatus(bool success) 651 { 652 if (!success) { 653 if (isWrite()) { 654 cmd = MemCmd::FunctionalWriteError; 655 } else { 656 cmd = MemCmd::FunctionalReadError; 657 } 658 } 659 } 660 661 /** 662 * Take a request packet that has been returned as NACKED and 663 * modify it so that it can be sent out again. Only packets that 664 * need a response can be NACKED, so verify that that is true. 665 */ 666 void 667 reinitNacked() 668 { 669 assert(wasNacked()); 670 cmd = origCmd; 671 assert(needsResponse()); 672 clearDest(); 673 } 674 675 void 676 setSize(unsigned size) 677 { 678 assert(!flags.isSet(VALID_SIZE)); 679 680 this->size = size; 681 flags.set(VALID_SIZE); 682 } 683 684 685 /** 686 * Set the data pointer to the following value that should not be 687 * freed. 688 */ 689 template <typename T> 690 void 691 dataStatic(T *p) 692 { 693 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); 694 data = (PacketDataPtr)p; 695 flags.set(STATIC_DATA); 696 } 697 698 /** 699 * Set the data pointer to a value that should have delete [] 700 * called on it. 701 */ 702 template <typename T> 703 void 704 dataDynamicArray(T *p) 705 { 706 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); 707 data = (PacketDataPtr)p; 708 flags.set(DYNAMIC_DATA|ARRAY_DATA); 709 } 710 711 /** 712 * set the data pointer to a value that should have delete called 713 * on it. 714 */ 715 template <typename T> 716 void 717 dataDynamic(T *p) 718 { 719 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA)); 720 data = (PacketDataPtr)p; 721 flags.set(DYNAMIC_DATA); 722 } 723 724 /** 725 * get a pointer to the data ptr. 726 */ 727 template <typename T> 728 T* 729 getPtr(bool null_ok = false) 730 { 731 assert(null_ok || flags.isSet(STATIC_DATA|DYNAMIC_DATA)); 732 return (T*)data; 733 } 734 735 /** 736 * return the value of what is pointed to in the packet. 737 */ 738 template <typename T> 739 T get(); 740 741 /** 742 * set the value in the data pointer to v. 743 */ 744 template <typename T> 745 void set(T v); 746 747 /** 748 * Copy data into the packet from the provided pointer. 749 */ 750 void 751 setData(uint8_t *p) 752 { 753 if (p != getPtr<uint8_t>()) 754 std::memcpy(getPtr<uint8_t>(), p, getSize()); 755 } 756 757 /** 758 * Copy data into the packet from the provided block pointer, 759 * which is aligned to the given block size. 760 */ 761 void 762 setDataFromBlock(uint8_t *blk_data, int blkSize) 763 { 764 setData(blk_data + getOffset(blkSize)); 765 } 766 767 /** 768 * Copy data from the packet to the provided block pointer, which 769 * is aligned to the given block size. 770 */ 771 void 772 writeData(uint8_t *p) 773 { 774 std::memcpy(p, getPtr<uint8_t>(), getSize()); 775 } 776 777 /** 778 * Copy data from the packet to the memory at the provided pointer. 779 */ 780 void 781 writeDataToBlock(uint8_t *blk_data, int blkSize) 782 { 783 writeData(blk_data + getOffset(blkSize)); 784 } 785 786 /** 787 * delete the data pointed to in the data pointer. Ok to call to 788 * matter how data was allocted. 789 */ 790 void 791 deleteData() 792 { 793 if (flags.isSet(ARRAY_DATA)) 794 delete [] data; 795 else if (flags.isSet(DYNAMIC_DATA)) 796 delete data; 797 798 flags.clear(STATIC_DATA|DYNAMIC_DATA|ARRAY_DATA); 799 data = NULL; 800 } 801 802 /** If there isn't data in the packet, allocate some. */ 803 void 804 allocate() 805 { 806 if (data) { 807 assert(flags.isSet(STATIC_DATA|DYNAMIC_DATA)); 808 return; 809 } 810 811 assert(flags.noneSet(STATIC_DATA|DYNAMIC_DATA)); 812 flags.set(DYNAMIC_DATA|ARRAY_DATA); 813 data = new uint8_t[getSize()]; 814 } 815 816 /** 817 * Check a functional request against a memory value represented 818 * by a base/size pair and an associated data array. If the 819 * functional request is a read, it may be satisfied by the memory 820 * value. If the functional request is a write, it may update the 821 * memory value. 822 */ 823 bool checkFunctional(Printable *obj, Addr base, int size, uint8_t *data); 824 825 /** 826 * Check a functional request against a memory value stored in 827 * another packet (i.e. an in-transit request or response). 828 */ 829 bool 830 checkFunctional(PacketPtr other) 831 { 832 uint8_t *data = other->hasData() ? other->getPtr<uint8_t>() : NULL; 833 return checkFunctional(other, other->getAddr(), other->getSize(), 834 data); 835 } 836 837 /** 838 * Push label for PrintReq (safe to call unconditionally). 839 */ 840 void 841 pushLabel(const std::string &lbl) 842 { 843 if (isPrint()) 844 safe_cast<PrintReqState*>(senderState)->pushLabel(lbl); 845 } 846 847 /** 848 * Pop label for PrintReq (safe to call unconditionally). 849 */ 850 void 851 popLabel() 852 { 853 if (isPrint()) 854 safe_cast<PrintReqState*>(senderState)->popLabel(); 855 } 856 857 void print(std::ostream &o, int verbosity = 0, 858 const std::string &prefix = "") const; 859}; 860 861#endif //__MEM_PACKET_HH 862